From ef12ba29d1c9137cd54218a62629534cdefa915b Mon Sep 17 00:00:00 2001 From: Vasa Date: Wed, 27 Aug 2025 21:24:13 +0300 Subject: [PATCH] fix --- package.json | 27 +--------- src/app.controller.ts | 99 ++++++++++++++++++++++------------ src/app.getaway.ts | 46 ++++++++-------- src/app.module.ts | 7 +-- src/main.ts | 14 ++--- src/services/prisma.service.ts | 8 +-- src/services/stats.service.ts | 53 +++++++++--------- src/stats.controller.ts | 26 ++++----- test/app.e2e-spec.ts | 25 --------- test/jest-e2e.json | 9 ---- 10 files changed, 140 insertions(+), 174 deletions(-) delete mode 100644 test/app.e2e-spec.ts delete mode 100644 test/jest-e2e.json diff --git a/package.json b/package.json index 5fa3b74..c47dd56 100644 --- a/package.json +++ b/package.json @@ -12,12 +12,7 @@ "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", "start:prod": "node dist/main", - "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", - "test": "jest", - "test:watch": "jest --watch", - "test:cov": "jest --coverage", - "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", - "test:e2e": "jest --config ./test/jest-e2e.json" + "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix" }, "dependencies": { "@nestjs/common": "^11.0.1", @@ -40,10 +35,8 @@ "@eslint/js": "^9.18.0", "@nestjs/cli": "^11.0.0", "@nestjs/schematics": "^11.0.0", - "@nestjs/testing": "^11.0.1", "@prisma/client": "^6.14.0", "@types/express": "^5.0.0", - "@types/jest": "^30.0.0", "@types/multer": "^2.0.0", "@types/node": "^22.10.7", "@types/supertest": "^6.0.2", @@ -51,7 +44,6 @@ "eslint-config-prettier": "^10.0.1", "eslint-plugin-prettier": "^5.2.2", "globals": "^16.0.0", - "jest": "^30.0.0", "prettier": "^3.4.2", "source-map-support": "^0.5.21", "supertest": "^7.0.0", @@ -61,22 +53,5 @@ "tsconfig-paths": "^4.2.0", "typescript": "^5.7.3", "typescript-eslint": "^8.20.0" - }, - "jest": { - "moduleFileExtensions": [ - "js", - "json", - "ts" - ], - "rootDir": "src", - "testRegex": ".*\\.spec\\.ts$", - "transform": { - "^.+\\.(t|j)s$": "ts-jest" - }, - "collectCoverageFrom": [ - "**/*.(t|j)s" - ], - "coverageDirectory": "../coverage", - "testEnvironment": "node" } } diff --git a/src/app.controller.ts b/src/app.controller.ts index 587caa1..f2743d4 100644 --- a/src/app.controller.ts +++ b/src/app.controller.ts @@ -1,4 +1,17 @@ -import { BadRequestException, Body, Controller, Delete, Get, NotFoundException, Param, ParseIntPipe, Post, Put, UploadedFile, UseInterceptors } from '@nestjs/common'; +import { + BadRequestException, + Body, + Controller, + Delete, + Get, + NotFoundException, + Param, + ParseIntPipe, + Post, + Put, + UploadedFile, + UseInterceptors, +} from '@nestjs/common'; import { RegisterDto } from './dto/register.dto'; import { ApiTags } from '@nestjs/swagger'; import { PrismaService } from './services/prisma.service'; @@ -11,8 +24,10 @@ import { unlink } from 'fs'; @ApiTags('App') @Controller('app') export class AppController { - constructor(private prisma: PrismaService, private socketService: AppGetaway) { } - + constructor( + private prisma: PrismaService, + private socketService: AppGetaway, + ) {} @Get('candidates') async getCandidateList() { @@ -23,12 +38,12 @@ export class AppController { age: true, cityOrRegion: true, profileImage: true, - } - }) + }, + }); data.forEach((candidate) => { candidate.profileImage = `${process.env.HOST_URL as string}/uploads/${candidate.profileImage}`; - }) + }); return data; } @@ -42,21 +57,23 @@ export class AppController { return data; } - @Post('register') - @UseInterceptors(FileInterceptor('profileImage', { - storage: diskStorage({ - destination: 'assets/uploads', - filename: (req, file, cb) => { - const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9); - const ext = extname(file.originalname); - cb(null, `${file.fieldname}-${uniqueSuffix}${ext}`); - } - }) - })) + @UseInterceptors( + FileInterceptor('profileImage', { + storage: diskStorage({ + destination: 'assets/uploads', + filename: (req, file, cb) => { + const uniqueSuffix = + Date.now() + '-' + Math.round(Math.random() * 1e9); + const ext = extname(file.originalname); + cb(null, `${file.fieldname}-${uniqueSuffix}${ext}`); + }, + }), + }), + ) async register( @UploadedFile() file: Express.Multer.File, - @Body() dto: RegisterDto + @Body() dto: RegisterDto, ) { const imagePath = file ? file.filename : null; const savedCandidate = await this.prisma.candidate.create({ @@ -72,27 +89,34 @@ export class AppController { } @Put('candidate/:id') - @UseInterceptors(FileInterceptor('profileImage', { - storage: diskStorage({ - destination: 'assets/uploads', - filename: (req, file, cb) => { - const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9); - const ext = extname(file.originalname); - cb(null, `${file.fieldname}-${uniqueSuffix}${ext}`); - } - }) - })) + @UseInterceptors( + FileInterceptor('profileImage', { + storage: diskStorage({ + destination: 'assets/uploads', + filename: (req, file, cb) => { + const uniqueSuffix = + Date.now() + '-' + Math.round(Math.random() * 1e9); + const ext = extname(file.originalname); + cb(null, `${file.fieldname}-${uniqueSuffix}${ext}`); + }, + }), + }), + ) async update( @Param('id', ParseIntPipe) id: number, @UploadedFile() file: Express.Multer.File, - @Body() dto: RegisterDto + @Body() dto: RegisterDto, ) { const candidate = await this.prisma.candidate.findFirst({ where: { id } }); - if (!candidate) throw new NotFoundException(`Candidate with id ${id} not found`); + if (!candidate) + throw new NotFoundException(`Candidate with id ${id} not found`); const dayMilliseconds = 86400000; - const expirationDate = new Date(candidate.createdAt.valueOf() + 3 * dayMilliseconds); - if (expirationDate < new Date()) throw new BadRequestException(`Cannot edit candidate form after 3 days`); + const expirationDate = new Date( + candidate.createdAt.valueOf() + 3 * dayMilliseconds, + ); + if (expirationDate < new Date()) + throw new BadRequestException(`Cannot edit candidate form after 3 days`); const profileImagePath = file ? file.filename : candidate.profileImage; @@ -108,16 +132,21 @@ export class AppController { return; } - @Delete('candidate/:id') async deleteCandidate(@Param('id', ParseIntPipe) id: number) { const candidate = await this.prisma.candidate.findFirst({ where: { id } }); - if (!candidate) throw new NotFoundException(`Candidate with id ${id} not found`); + if (!candidate) + throw new NotFoundException(`Candidate with id ${id} not found`); await this.prisma.candidate.delete({ where: { id } }); if (candidate.profileImage) { - const filePath = join(process.cwd(), 'assets', 'uploads', candidate.profileImage); + const filePath = join( + process.cwd(), + 'assets', + 'uploads', + candidate.profileImage, + ); unlink(filePath, (err) => { if (err) { console.error('Failed to delete file:', err); diff --git a/src/app.getaway.ts b/src/app.getaway.ts index 1db517a..dd931fb 100644 --- a/src/app.getaway.ts +++ b/src/app.getaway.ts @@ -1,30 +1,34 @@ -import { MessageBody, OnGatewayConnection, OnGatewayDisconnect, SubscribeMessage, WebSocketGateway, WebSocketServer } from "@nestjs/websockets"; -import { Server, Socket } from "socket.io"; +import { + OnGatewayConnection, + OnGatewayDisconnect, + WebSocketGateway, + WebSocketServer, +} from '@nestjs/websockets'; +import { Server, Socket } from 'socket.io'; @WebSocketGateway({ - cors: true + cors: true, }) - export class AppGetaway implements OnGatewayDisconnect, OnGatewayConnection { - @WebSocketServer() server: Server + @WebSocketServer() server: Server; - handleDisconnect(client: Socket) { - console.log(`${client.id} disconnected`) - } + handleDisconnect(client: Socket) { + console.log(`${client.id} disconnected`); + } - handleConnection(client: Socket, ...args: any[]) { - console.log(`${client.id} connected`) - } + handleConnection(client: Socket /*...args: any[]*/) { + console.log(`${client.id} connected`); + } - onAddCandidate(registrationData: any) { - this.server.emit('candidateRegistered', registrationData); - } + onAddCandidate(registrationData: any) { + this.server.emit('candidateRegistered', registrationData); + } - onUpdateCandidate(updatedData: any) { - this.server.emit('candidateUpdated', updatedData); - } + onUpdateCandidate(updatedData: any) { + this.server.emit('candidateUpdated', updatedData); + } - onDeleteCandidate(deletedId: number) { - this.server.emit('candidateDeleted', deletedId); - } -} \ No newline at end of file + onDeleteCandidate(deletedId: number) { + this.server.emit('candidateDeleted', deletedId); + } +} diff --git a/src/app.module.ts b/src/app.module.ts index 38dd16e..34cc1b4 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -14,14 +14,15 @@ import { ConfigModule } from '@nestjs/config'; ServeStaticModule.forRoot( { rootPath: join(__dirname, 'assets/client'), - renderPath: '/' + renderPath: '/', }, { rootPath: join(__dirname, 'assets/uploads'), serveRoot: '/uploads', - }), + }, + ), ], controllers: [AppController, StatsController], providers: [PrismaService, StatsService, AppGetaway], }) -export class AppModule { } +export class AppModule {} diff --git a/src/main.ts b/src/main.ts index a1fa38a..ba37116 100644 --- a/src/main.ts +++ b/src/main.ts @@ -15,19 +15,11 @@ async function bootstrap() { setupSwagger(app); app.enableCors({ origin: [true], - methods: [ - 'GET', - 'HEAD', - 'PUT', - 'PATCH', - 'POST', - 'DELETE', - 'OPTIONS', - ], + methods: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE', 'OPTIONS'], allowedHeaders: ['*'], optionsSuccessStatus: 204, credentials: true, - preflightContinue: false + preflightContinue: false, }); await app.listen(process.env.PORT ?? 3000); } @@ -43,5 +35,5 @@ function setupSwagger(app: INestApplication) { SwaggerModule.setup('api', app, document); } +// eslint-disable-next-line @typescript-eslint/no-floating-promises bootstrap(); - diff --git a/src/services/prisma.service.ts b/src/services/prisma.service.ts index 540f456..5cbedb3 100644 --- a/src/services/prisma.service.ts +++ b/src/services/prisma.service.ts @@ -3,7 +3,7 @@ import { PrismaClient } from 'generated/prisma'; @Injectable() export class PrismaService extends PrismaClient implements OnModuleInit { - async onModuleInit() { - await this.$connect(); - } -} \ No newline at end of file + async onModuleInit() { + await this.$connect(); + } +} diff --git a/src/services/stats.service.ts b/src/services/stats.service.ts index cfa83ee..31a9ade 100644 --- a/src/services/stats.service.ts +++ b/src/services/stats.service.ts @@ -1,34 +1,33 @@ -import { Injectable } from "@nestjs/common"; -import { PrismaService } from "./prisma.service"; -import { AppGetaway } from "src/app.getaway"; - +import { Injectable } from '@nestjs/common'; +import { PrismaService } from './prisma.service'; +import { AppGetaway } from 'src/app.getaway'; @Injectable() export class StatsService { - constructor( - private prisma: PrismaService, - private socketService: AppGetaway - ) { } + constructor( + private prisma: PrismaService, + private socketService: AppGetaway, + ) {} - async incrementVisits() { - const stats = await this.prisma.stats.update({ - where: { id: 1 }, - data: { totalVisits: { increment: 1 } }, - }); - this.socketService.server.emit('statsUpdated', stats); - return stats; - } + async incrementVisits() { + const stats = await this.prisma.stats.update({ + where: { id: 1 }, + data: { totalVisits: { increment: 1 } }, + }); + this.socketService.server.emit('statsUpdated', stats); + return stats; + } - async incrementClicks() { - const stats = await this.prisma.stats.update({ - where: { id: 1 }, - data: { totalClicks: { increment: 1 } }, - }); - this.socketService.server.emit('statsUpdated', stats); - return stats; - } + async incrementClicks() { + const stats = await this.prisma.stats.update({ + where: { id: 1 }, + data: { totalClicks: { increment: 1 } }, + }); + this.socketService.server.emit('statsUpdated', stats); + return stats; + } - async getStats() { - return this.prisma.stats.findUnique({ where: { id: 1 } }); - } + async getStats() { + return this.prisma.stats.findUnique({ where: { id: 1 } }); + } } diff --git a/src/stats.controller.ts b/src/stats.controller.ts index 4be41e8..0e361a9 100644 --- a/src/stats.controller.ts +++ b/src/stats.controller.ts @@ -3,20 +3,20 @@ import { StatsService } from './services/stats.service'; @Controller('stats') export class StatsController { - constructor(private readonly statsService: StatsService) { } + constructor(private readonly statsService: StatsService) {} - @Get() - getStats() { - return this.statsService.getStats(); - } + @Get() + getStats() { + return this.statsService.getStats(); + } - @Post('visit') - incrementVisit() { - return this.statsService.incrementVisits(); - } + @Post('visit') + incrementVisit() { + return this.statsService.incrementVisits(); + } - @Post('click') - incrementClick() { - return this.statsService.incrementClicks(); - } + @Post('click') + incrementClick() { + return this.statsService.incrementClicks(); + } } diff --git a/test/app.e2e-spec.ts b/test/app.e2e-spec.ts deleted file mode 100644 index 4df6580..0000000 --- a/test/app.e2e-spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { INestApplication } from '@nestjs/common'; -import * as request from 'supertest'; -import { App } from 'supertest/types'; -import { AppModule } from './../src/app.module'; - -describe('AppController (e2e)', () => { - let app: INestApplication; - - beforeEach(async () => { - const moduleFixture: TestingModule = await Test.createTestingModule({ - imports: [AppModule], - }).compile(); - - app = moduleFixture.createNestApplication(); - await app.init(); - }); - - it('/ (GET)', () => { - return request(app.getHttpServer()) - .get('/') - .expect(200) - .expect('Hello World!'); - }); -}); diff --git a/test/jest-e2e.json b/test/jest-e2e.json deleted file mode 100644 index e9d912f..0000000 --- a/test/jest-e2e.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "moduleFileExtensions": ["js", "json", "ts"], - "rootDir": ".", - "testEnvironment": "node", - "testRegex": ".e2e-spec.ts$", - "transform": { - "^.+\\.(t|j)s$": "ts-jest" - } -}