From 781f3d102aa3c33aed2574441d22dceb3ddd567d Mon Sep 17 00:00:00 2001 From: J_Coder Date: Wed, 8 Jan 2025 17:25:53 +0900 Subject: [PATCH 1/7] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor:=20admin=20dt?= =?UTF-8?q?o=20request/response=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/src/admin/controller/admin.controller.ts | 11 +++++------ .../src/admin/dto/{ => request}/login-admin.dto.ts | 2 +- .../admin/dto/{ => request}/register-admin.dto.ts | 2 +- server/src/admin/repository/admin.repository.ts | 4 ++-- server/src/admin/service/admin.service.ts | 8 ++++---- server/test/admin/dto/login-admin.dto.spec.ts | 6 +++--- server/test/admin/dto/register-admin.dto.spec.ts | 6 +++--- server/test/admin/e2e/login.e2e-spec.ts | 12 ++++++------ server/test/admin/e2e/register.e2e-spec.ts | 10 +++++----- server/test/admin/e2e/sessionId.e2e-spec.ts | 4 ++-- 10 files changed, 32 insertions(+), 33 deletions(-) rename server/src/admin/dto/{ => request}/login-admin.dto.ts (94%) rename server/src/admin/dto/{ => request}/register-admin.dto.ts (96%) diff --git a/server/src/admin/controller/admin.controller.ts b/server/src/admin/controller/admin.controller.ts index e6e5aaf..580011e 100644 --- a/server/src/admin/controller/admin.controller.ts +++ b/server/src/admin/controller/admin.controller.ts @@ -13,10 +13,10 @@ import { } from '@nestjs/common'; import { Request, Response } from 'express'; import { AdminService } from '../service/admin.service'; -import { RegisterAdminDto } from '../dto/register-admin.dto'; +import { RegisterAdminRequestDto } from '../dto/request/register-admin.dto'; import { ApiTags } from '@nestjs/swagger'; import { ApiResponse } from '../../common/response/common.response'; -import { LoginAdminDto } from '../dto/login-admin.dto'; +import { LoginAdminRequestDto } from '../dto/request/login-admin.dto'; import { CookieAuthGuard } from '../../common/guard/auth.guard'; import { ApiLoginAdmin } from '../api-docs/loginAdmin.api-docs'; import { ApiReadSessionIdAdmin } from '../api-docs/readSessionIdAdmin.api-docs'; @@ -33,7 +33,7 @@ export class AdminController { @HttpCode(HttpStatus.OK) @UsePipes(ValidationPipe) async loginAdmin( - @Body() loginAdminDto: LoginAdminDto, + @Body() loginAdminDto: LoginAdminRequestDto, @Res({ passthrough: true }) response: Response, @Req() request: Request, ) { @@ -49,8 +49,7 @@ export class AdminController { @Post('/logout') async logoutAdmin( @Req() request: Request, - @Res({ passthrough: true }) - response: Response, + @Res({ passthrough: true }) response: Response, ) { await this.adminService.logoutAdmin(request, response); return ApiResponse.responseWithNoContent( @@ -62,7 +61,7 @@ export class AdminController { @UseGuards(CookieAuthGuard) @Post('/register') @UsePipes(ValidationPipe) - async createAdmin(@Body() registerAdminDto: RegisterAdminDto) { + async createAdmin(@Body() registerAdminDto: RegisterAdminRequestDto) { await this.adminService.createAdmin(registerAdminDto); return ApiResponse.responseWithNoContent( '성공적으로 관리자 계정이 생성되었습니다.', diff --git a/server/src/admin/dto/login-admin.dto.ts b/server/src/admin/dto/request/login-admin.dto.ts similarity index 94% rename from server/src/admin/dto/login-admin.dto.ts rename to server/src/admin/dto/request/login-admin.dto.ts index 080cdd3..f497a26 100644 --- a/server/src/admin/dto/login-admin.dto.ts +++ b/server/src/admin/dto/request/login-admin.dto.ts @@ -1,7 +1,7 @@ import { IsNotEmpty, IsString } from 'class-validator'; import { ApiProperty } from '@nestjs/swagger'; -export class LoginAdminDto { +export class LoginAdminRequestDto { @ApiProperty({ example: 'minseokjo', description: '관리자 로그인 아이디를 입력해주세요.', diff --git a/server/src/admin/dto/register-admin.dto.ts b/server/src/admin/dto/request/register-admin.dto.ts similarity index 96% rename from server/src/admin/dto/register-admin.dto.ts rename to server/src/admin/dto/request/register-admin.dto.ts index 7ae2e7e..e981217 100644 --- a/server/src/admin/dto/register-admin.dto.ts +++ b/server/src/admin/dto/request/register-admin.dto.ts @@ -3,7 +3,7 @@ import { ApiProperty } from '@nestjs/swagger'; const PASSWORD_REG = /^(?=.*[!@#$%^&*()_+])[A-Za-z0-9!@#$%^&*()_+]+$/; -export class RegisterAdminDto { +export class RegisterAdminRequestDto { @ApiProperty({ example: 'minseokjo', description: '관리자 로그인 아이디를 입력해주세요.', diff --git a/server/src/admin/repository/admin.repository.ts b/server/src/admin/repository/admin.repository.ts index 8077340..207ad64 100644 --- a/server/src/admin/repository/admin.repository.ts +++ b/server/src/admin/repository/admin.repository.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { DataSource, Repository } from 'typeorm'; import { Admin } from '../entity/admin.entity'; -import { RegisterAdminDto } from '../dto/register-admin.dto'; +import { RegisterAdminRequestDto } from '../dto/request/register-admin.dto'; @Injectable() export class AdminRepository extends Repository { @@ -9,7 +9,7 @@ export class AdminRepository extends Repository { super(Admin, dataSource.createEntityManager()); } - async createAdmin(registerAdminDto: RegisterAdminDto) { + async createAdmin(registerAdminDto: RegisterAdminRequestDto) { const { loginId, password } = registerAdminDto; const admin = this.create({ loginId, diff --git a/server/src/admin/service/admin.service.ts b/server/src/admin/service/admin.service.ts index 7b29bc7..68e17b6 100644 --- a/server/src/admin/service/admin.service.ts +++ b/server/src/admin/service/admin.service.ts @@ -4,13 +4,13 @@ import { UnauthorizedException, } from '@nestjs/common'; import { Response, Request } from 'express'; -import { RegisterAdminDto } from '../dto/register-admin.dto'; +import { RegisterAdminRequestDto } from '../dto/request/register-admin.dto'; import { AdminRepository } from '../repository/admin.repository'; import * as bcrypt from 'bcrypt'; import { cookieConfig } from '../../common/cookie/cookie.config'; import * as uuid from 'uuid'; import { RedisService } from '../../common/redis/redis.service'; -import { LoginAdminDto } from '../dto/login-admin.dto'; +import { LoginAdminRequestDto } from '../dto/request/login-admin.dto'; @Injectable() export class AdminService { @@ -23,7 +23,7 @@ export class AdminService { ) {} async loginAdmin( - loginAdminDto: LoginAdminDto, + loginAdminDto: LoginAdminRequestDto, response: Response, request: Request, ) { @@ -92,7 +92,7 @@ export class AdminService { response.clearCookie('sessionId'); } - async createAdmin(registerAdminDto: RegisterAdminDto) { + async createAdmin(registerAdminDto: RegisterAdminRequestDto) { let { loginId, password } = registerAdminDto; const existingAdmin = await this.adminRepository.findOne({ diff --git a/server/test/admin/dto/login-admin.dto.spec.ts b/server/test/admin/dto/login-admin.dto.spec.ts index dcfadbd..e11335e 100644 --- a/server/test/admin/dto/login-admin.dto.spec.ts +++ b/server/test/admin/dto/login-admin.dto.spec.ts @@ -1,11 +1,11 @@ -import { LoginAdminDto } from '../../../src/admin/dto/login-admin.dto'; +import { LoginAdminRequestDto } from '../../../src/admin/dto/request/login-admin.dto'; import { validate } from 'class-validator'; describe('LoginAdminDto Test', () => { - let loginAdminDto: LoginAdminDto; + let loginAdminDto: LoginAdminRequestDto; beforeEach(() => { - loginAdminDto = new LoginAdminDto(); + loginAdminDto = new LoginAdminRequestDto(); }); it('ID에 null이 입력되면 유효성 검사에 실패한다.', async () => { diff --git a/server/test/admin/dto/register-admin.dto.spec.ts b/server/test/admin/dto/register-admin.dto.spec.ts index 601f7b3..f8ab6fc 100644 --- a/server/test/admin/dto/register-admin.dto.spec.ts +++ b/server/test/admin/dto/register-admin.dto.spec.ts @@ -1,11 +1,11 @@ -import { RegisterAdminDto } from '../../../src/admin/dto/register-admin.dto'; +import { RegisterAdminRequestDto } from '../../../src/admin/dto/request/register-admin.dto'; import { validate } from 'class-validator'; describe('LoginAdminDto Test', () => { - let registerAdminDto: RegisterAdminDto; + let registerAdminDto: RegisterAdminRequestDto; beforeEach(() => { - registerAdminDto = new RegisterAdminDto(); + registerAdminDto = new RegisterAdminRequestDto(); }); it('ID의 길이가 6 이상, 255 이하가 아니라면 유효성 검사에 실패한다.', async () => { diff --git a/server/test/admin/e2e/login.e2e-spec.ts b/server/test/admin/e2e/login.e2e-spec.ts index 547e535..e80c1ff 100644 --- a/server/test/admin/e2e/login.e2e-spec.ts +++ b/server/test/admin/e2e/login.e2e-spec.ts @@ -1,12 +1,12 @@ import { INestApplication } from '@nestjs/common'; import { AdminService } from '../../../src/admin/service/admin.service'; -import { LoginAdminDto } from '../../../src/admin/dto/login-admin.dto'; +import { LoginAdminRequestDto } from '../../../src/admin/dto/request/login-admin.dto'; import * as request from 'supertest'; -import { RegisterAdminDto } from '../../../src/admin/dto/register-admin.dto'; +import { RegisterAdminRequestDto } from '../../../src/admin/dto/request/register-admin.dto'; describe('POST api/admin/login E2E Test', () => { let app: INestApplication; let adminService: AdminService; - const registerAdminDto: RegisterAdminDto = { + const registerAdminDto: RegisterAdminRequestDto = { loginId: 'testAdminId', password: 'testAdminPassword!', }; @@ -18,7 +18,7 @@ describe('POST api/admin/login E2E Test', () => { }); it('등록된 계정이면 정상적으로 로그인할 수 있다.', async () => { //given - const loginAdminDto: LoginAdminDto = { + const loginAdminDto: LoginAdminRequestDto = { loginId: 'testAdminId', password: 'testAdminPassword!', }; @@ -35,7 +35,7 @@ describe('POST api/admin/login E2E Test', () => { it('등록되지 않은 ID로 로그인을 시도하면 401 UnAuthorized 예외가 발생한다.', async () => { //given - const loginWrongAdminIdDto: LoginAdminDto = { + const loginWrongAdminIdDto: LoginAdminRequestDto = { loginId: 'testWrongAdminId', password: 'testAdminPassword!', }; @@ -51,7 +51,7 @@ describe('POST api/admin/login E2E Test', () => { it('비밀번호가 다르다면 401 UnAuthorized 예외가 발생한다.', async () => { //given - const loginWrongAdminPasswordDto: LoginAdminDto = { + const loginWrongAdminPasswordDto: LoginAdminRequestDto = { loginId: 'testAdminId', password: 'testWrongAdminPassword!', }; diff --git a/server/test/admin/e2e/register.e2e-spec.ts b/server/test/admin/e2e/register.e2e-spec.ts index 8f30eea..49bd4ab 100644 --- a/server/test/admin/e2e/register.e2e-spec.ts +++ b/server/test/admin/e2e/register.e2e-spec.ts @@ -1,7 +1,7 @@ import { INestApplication } from '@nestjs/common'; import { AdminService } from '../../../src/admin/service/admin.service'; -import { LoginAdminDto } from '../../../src/admin/dto/login-admin.dto'; -import { RegisterAdminDto } from '../../../src/admin/dto/register-admin.dto'; +import { LoginAdminRequestDto } from '../../../src/admin/dto/request/login-admin.dto'; +import { RegisterAdminRequestDto } from '../../../src/admin/dto/request/register-admin.dto'; import * as request from 'supertest'; describe('POST api/admin/register E2E Test', () => { @@ -9,11 +9,11 @@ describe('POST api/admin/register E2E Test', () => { let adminService: AdminService; //given - const loginAdminDto: LoginAdminDto = { + const loginAdminDto: LoginAdminRequestDto = { loginId: 'testAdminId', password: 'testAdminPassword!', }; - const registerAdminDto: RegisterAdminDto = { + const registerAdminDto: RegisterAdminRequestDto = { loginId: 'testNewAdminId', password: 'testNewAdminPassword!', }; @@ -55,7 +55,7 @@ describe('POST api/admin/register E2E Test', () => { it('관리자가 로그아웃 상태면 401 UnAuthorized 예외가 발생한다.', async () => { //given - const registerAdminDto: RegisterAdminDto = { + const registerAdminDto: RegisterAdminRequestDto = { loginId: 'testNewAdminId', password: 'testNewAdminPassword!', }; diff --git a/server/test/admin/e2e/sessionId.e2e-spec.ts b/server/test/admin/e2e/sessionId.e2e-spec.ts index 06c5bc3..ce7c4f1 100644 --- a/server/test/admin/e2e/sessionId.e2e-spec.ts +++ b/server/test/admin/e2e/sessionId.e2e-spec.ts @@ -1,6 +1,6 @@ import { INestApplication } from '@nestjs/common'; import { AdminService } from '../../../src/admin/service/admin.service'; -import { LoginAdminDto } from '../../../src/admin/dto/login-admin.dto'; +import { LoginAdminRequestDto } from '../../../src/admin/dto/request/login-admin.dto'; import * as request from 'supertest'; import { v4 as uuidv4 } from 'uuid'; @@ -9,7 +9,7 @@ describe('GET api/admin/sessionId E2E Test', () => { let adminService: AdminService; //given - const loginAdminDto: LoginAdminDto = { + const loginAdminDto: LoginAdminRequestDto = { loginId: 'testAdminId', password: 'testAdminPassword!', }; From 704a266e8c6f962cec6cca5cac21f2ce64383466 Mon Sep 17 00:00:00 2001 From: J_Coder Date: Wed, 8 Jan 2025 18:52:05 +0900 Subject: [PATCH 2/7] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor:=20feed=20dto?= =?UTF-8?q?=20request/response=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feed/api-docs/searchFeedList.api-docs.ts | 2 +- server/src/feed/controller/feed.controller.ts | 45 ++++++++++--------- .../feed-pagination.dto.ts} | 2 +- .../feed/dto/{ => request}/search-feed.dto.ts | 36 +-------------- .../feed-pagination.dto.ts} | 22 +++++---- server/src/feed/dto/response/recent.dto.ts | 43 ++++++++++++++++++ .../src/feed/dto/response/search-feed.dto.ts | 32 +++++++++++++ server/src/feed/repository/feed.repository.ts | 6 +-- server/src/feed/service/feed.service.ts | 45 ++++++++++--------- ...to.spec.ts => feed-pagination.dto.spec.ts} | 8 ++-- ...ch.dto.spec.ts => search-feed.dto.spec.ts} | 10 ++--- 11 files changed, 155 insertions(+), 96 deletions(-) rename server/src/feed/dto/{query-feed.dto.ts => request/feed-pagination.dto.ts} (92%) rename server/src/feed/dto/{ => request}/search-feed.dto.ts (54%) rename server/src/feed/dto/{feed-response.dto.ts => response/feed-pagination.dto.ts} (75%) create mode 100644 server/src/feed/dto/response/recent.dto.ts create mode 100644 server/src/feed/dto/response/search-feed.dto.ts rename server/test/feed/dto/{query-feed.dto.spec.ts => feed-pagination.dto.spec.ts} (89%) rename server/test/feed/dto/{query-search.dto.spec.ts => search-feed.dto.spec.ts} (92%) diff --git a/server/src/feed/api-docs/searchFeedList.api-docs.ts b/server/src/feed/api-docs/searchFeedList.api-docs.ts index 813e1cd..287e331 100644 --- a/server/src/feed/api-docs/searchFeedList.api-docs.ts +++ b/server/src/feed/api-docs/searchFeedList.api-docs.ts @@ -5,7 +5,7 @@ import { ApiOperation, ApiQuery, } from '@nestjs/swagger'; -import { SearchType } from '../dto/search-feed.dto'; +import { SearchType } from '../dto/request/search-feed.dto'; export function ApiSearchFeedList() { return applyDecorators( diff --git a/server/src/feed/controller/feed.controller.ts b/server/src/feed/controller/feed.controller.ts index c99f75a..3ef169b 100644 --- a/server/src/feed/controller/feed.controller.ts +++ b/server/src/feed/controller/feed.controller.ts @@ -15,8 +15,8 @@ import { ValidationPipe, } from '@nestjs/common'; import { FeedService } from '../service/feed.service'; -import { QueryFeedDto } from '../dto/query-feed.dto'; -import { SearchFeedReq } from '../dto/search-feed.dto'; +import { FeedPaginationRequestDto } from '../dto/request/feed-pagination.dto'; +import { SearchFeedRequestDto } from '../dto/request/search-feed.dto'; import { Response, Request } from 'express'; import { Observable } from 'rxjs'; import { EventEmitter2 } from '@nestjs/event-emitter'; @@ -25,7 +25,7 @@ import { ApiReadTrendFeedList } from '../api-docs/readTrendFeedList.api-docs'; import { ApiSearchFeedList } from '../api-docs/searchFeedList.api-docs'; import { ApiUpdateFeedViewCount } from '../api-docs/updateFeedViewCount.api-docs'; import { ApiReadRecentFeedList } from '../api-docs/readRecentFeedList.api-docs'; -import { Feed } from '../entity/feed.entity'; +import { FeedTrendResponseDto } from '../dto/response/feed-pagination.dto'; @ApiTags('Feed') @Controller('feed') @@ -43,7 +43,7 @@ export class FeedController { transform: true, }), ) - async readFeedPagination(@Query() queryFeedDto: QueryFeedDto) { + async readFeedPagination(@Query() queryFeedDto: FeedPaginationRequestDto) { return ApiResponse.responseWithData( '피드 조회 완료', await this.feedService.readFeedPagination(queryFeedDto), @@ -54,22 +54,27 @@ export class FeedController { @Sse('trend/sse') async readTrendFeedList() { return new Observable((observer) => { - this.feedService.readTrendFeedList().then((trendData) => { - observer.next({ - data: { - message: '현재 트렌드 피드 수신 완료', - data: trendData, - }, + this.feedService + .readTrendFeedList() + .then((trendData: FeedTrendResponseDto[]) => { + observer.next({ + data: { + message: '현재 트렌드 피드 수신 완료', + data: trendData, + }, + }); }); - }); - this.eventService.on('ranking-update', (trendData: Feed[]) => { - observer.next({ - data: { - message: '새로운 트렌드 피드 수신 완료', - data: trendData, - }, - }); - }); + this.eventService.on( + 'ranking-update', + (trendData: FeedTrendResponseDto[]) => { + observer.next({ + data: { + message: '새로운 트렌드 피드 수신 완료', + data: trendData, + }, + }); + }, + ); }); } @@ -82,7 +87,7 @@ export class FeedController { }), new ValidationPipe(), ) - async searchFeedList(@Query() searchFeedReq: SearchFeedReq) { + async searchFeedList(@Query() searchFeedReq: SearchFeedRequestDto) { const data = await this.feedService.searchFeedList(searchFeedReq); return ApiResponse.responseWithData('검색 결과 조회 완료', data); } diff --git a/server/src/feed/dto/query-feed.dto.ts b/server/src/feed/dto/request/feed-pagination.dto.ts similarity index 92% rename from server/src/feed/dto/query-feed.dto.ts rename to server/src/feed/dto/request/feed-pagination.dto.ts index 88d34ad..fcbfe2e 100644 --- a/server/src/feed/dto/query-feed.dto.ts +++ b/server/src/feed/dto/request/feed-pagination.dto.ts @@ -1,7 +1,7 @@ import { IsInt, IsOptional, Min } from 'class-validator'; import { Type } from 'class-transformer'; -export class QueryFeedDto { +export class FeedPaginationRequestDto { @IsOptional() @Min(0, { message: 'lastId 값은 0 이상이어야 합니다.' }) @IsInt({ diff --git a/server/src/feed/dto/search-feed.dto.ts b/server/src/feed/dto/request/search-feed.dto.ts similarity index 54% rename from server/src/feed/dto/search-feed.dto.ts rename to server/src/feed/dto/request/search-feed.dto.ts index 3b51c85..93f4b68 100644 --- a/server/src/feed/dto/search-feed.dto.ts +++ b/server/src/feed/dto/request/search-feed.dto.ts @@ -1,4 +1,3 @@ -import { Feed } from '../../feed/entity/feed.entity'; import { IsDefined, IsEnum, IsInt, IsString, Min } from 'class-validator'; import { Type } from 'class-transformer'; @@ -8,7 +7,7 @@ export enum SearchType { ALL = 'all', } -export class SearchFeedReq { +export class SearchFeedRequestDto { @IsDefined({ message: '검색어를 입력해주세요.', }) @@ -37,38 +36,7 @@ export class SearchFeedReq { @Type(() => Number) limit?: number = 4; - constructor(partial: Partial) { + constructor(partial: Partial) { Object.assign(this, partial); } } - -export class SearchFeedResult { - constructor( - private id: number, - private blogName: string, - private title: string, - private path: string, - private createdAt: Date, - ) {} - - static feedsToResults(feeds: Feed[]): SearchFeedResult[] { - return feeds.map((item) => { - return new SearchFeedResult( - item.id, - item.blog.name, - item.title, - item.path, - item.createdAt, - ); - }); - } -} - -export class SearchFeedRes { - constructor( - private totalCount: number, - private result: SearchFeedResult[], - private totalPages: number, - private limit: number, - ) {} -} diff --git a/server/src/feed/dto/feed-response.dto.ts b/server/src/feed/dto/response/feed-pagination.dto.ts similarity index 75% rename from server/src/feed/dto/feed-response.dto.ts rename to server/src/feed/dto/response/feed-pagination.dto.ts index 8edc120..7ac667a 100644 --- a/server/src/feed/dto/feed-response.dto.ts +++ b/server/src/feed/dto/response/feed-pagination.dto.ts @@ -1,6 +1,6 @@ -import { FeedView } from '../../feed/entity/feed.entity'; +import { FeedView } from '../../entity/feed.entity'; -export class FeedPaginationResponseDto { +export class FeedResult { private constructor( private id: number, private author: string, @@ -13,8 +13,8 @@ export class FeedPaginationResponseDto { private isNew: boolean, ) {} - private static toFeedPaginationResponseDto(feed: FeedPaginationResult) { - return new FeedPaginationResponseDto( + private static toPaginationResultDto(feed: FeedPaginationResult) { + return new FeedResult( feed.feedId, feed.blogName, feed.blogPlatform, @@ -27,13 +27,19 @@ export class FeedPaginationResponseDto { ); } - public static mapToPaginationResponseDtoArray( - FeedList: FeedPaginationResult[], - ) { - return FeedList.map(this.toFeedPaginationResponseDto); + public static toPaginationResultDtoArray(feedList: FeedPaginationResult[]) { + return feedList.map(this.toPaginationResultDto); } } +export class FeedPaginationResponseDto { + constructor( + private result: FeedResult[], + private lastId: number, + private hasMore: boolean, + ) {} +} + export type FeedPaginationResult = FeedView & { isNew: boolean }; export class FeedTrendResponseDto { diff --git a/server/src/feed/dto/response/recent.dto.ts b/server/src/feed/dto/response/recent.dto.ts new file mode 100644 index 0000000..1efb259 --- /dev/null +++ b/server/src/feed/dto/response/recent.dto.ts @@ -0,0 +1,43 @@ +export class FeedRecentResponseDto { + constructor( + private id: number, + private author: string, + private blogPlatform: string, + private title: string, + private path: string, + private createdAt: string, + private thumbnail: string, + private viewCount: number, + private isNew: boolean, + ) {} + + static toRecentResponseDto(feed: FeedRecentRedis) { + return new FeedRecentResponseDto( + feed.id, + feed.blogName, + feed.blogPlatform, + feed.title, + feed.path, + feed.createdAt, + feed.thumbnail, + feed.viewCount, + feed.isNew, + ); + } + + static toRecentResponseDtoArray(feeds: FeedRecentRedis[]) { + return feeds.map(this.toRecentResponseDto); + } +} + +export type FeedRecentRedis = { + id: number; + blogPlatform: string; + createdAt: string; + viewCount: number; + blogName: string; + thumbnail: string; + path: string; + title: string; + isNew?: boolean; +}; diff --git a/server/src/feed/dto/response/search-feed.dto.ts b/server/src/feed/dto/response/search-feed.dto.ts new file mode 100644 index 0000000..e5fb892 --- /dev/null +++ b/server/src/feed/dto/response/search-feed.dto.ts @@ -0,0 +1,32 @@ +import { Feed } from '../../entity/feed.entity'; + +export class SearchFeedResult { + constructor( + private id: number, + private blogName: string, + private title: string, + private path: string, + private createdAt: Date, + ) {} + + static feedsToResults(feeds: Feed[]): SearchFeedResult[] { + return feeds.map((item) => { + return new SearchFeedResult( + item.id, + item.blog.name, + item.title, + item.path, + item.createdAt, + ); + }); + } +} + +export class SearchFeedResponseDto { + constructor( + private totalCount: number, + private result: SearchFeedResult[], + private totalPages: number, + private limit: number, + ) {} +} diff --git a/server/src/feed/repository/feed.repository.ts b/server/src/feed/repository/feed.repository.ts index 50ba549..c5aacd0 100644 --- a/server/src/feed/repository/feed.repository.ts +++ b/server/src/feed/repository/feed.repository.ts @@ -1,8 +1,8 @@ import { DataSource, Repository } from 'typeorm'; import { Feed, FeedView } from '../entity/feed.entity'; import { Injectable } from '@nestjs/common'; -import { QueryFeedDto } from '../dto/query-feed.dto'; -import { SearchType } from '../dto/search-feed.dto'; +import { FeedPaginationRequestDto } from '../dto/request/feed-pagination.dto'; +import { SearchType } from '../dto/request/search-feed.dto'; @Injectable() export class FeedRepository extends Repository { @@ -67,7 +67,7 @@ export class FeedViewRepository extends Repository { super(FeedView, dataSource.createEntityManager()); } - async findFeedPagination(queryFeedDto: QueryFeedDto) { + async findFeedPagination(queryFeedDto: FeedPaginationRequestDto) { const { lastId, limit } = queryFeedDto; const query = this.createQueryBuilder() .where((qb) => { diff --git a/server/src/feed/service/feed.service.ts b/server/src/feed/service/feed.service.ts index ebdc0cb..fb1f835 100644 --- a/server/src/feed/service/feed.service.ts +++ b/server/src/feed/service/feed.service.ts @@ -7,25 +7,30 @@ import { FeedRepository, FeedViewRepository, } from '../repository/feed.repository'; -import { QueryFeedDto } from '../dto/query-feed.dto'; +import { FeedPaginationRequestDto } from '../dto/request/feed-pagination.dto'; import { FeedView } from '../entity/feed.entity'; import { - FeedPaginationResult, FeedPaginationResponseDto, + FeedPaginationResult, + FeedResult, FeedTrendResponseDto, -} from '../dto/feed-response.dto'; +} from '../dto/response/feed-pagination.dto'; import { RedisService } from '../../common/redis/redis.service'; import { Cron, CronExpression } from '@nestjs/schedule'; import { EventEmitter2 } from '@nestjs/event-emitter'; import * as _ from 'lodash'; -import { - SearchFeedReq, - SearchFeedRes, - SearchFeedResult, -} from '../dto/search-feed.dto'; +import { SearchFeedRequestDto } from '../dto/request/search-feed.dto'; import { Response, Request } from 'express'; import { cookieConfig } from '../../common/cookie/cookie.config'; import { redisKeys } from '../../common/redis/redis.constant'; +import { + SearchFeedResponseDto, + SearchFeedResult, +} from '../dto/response/search-feed.dto'; +import { + FeedRecentRedis, + FeedRecentResponseDto, +} from '../dto/response/recent.dto'; @Injectable() export class FeedService { @@ -36,18 +41,15 @@ export class FeedService { private readonly eventService: EventEmitter2, ) {} - async readFeedPagination(queryFeedDto: QueryFeedDto) { + async readFeedPagination(queryFeedDto: FeedPaginationRequestDto) { const feedList = await this.feedViewRepository.findFeedPagination(queryFeedDto); const hasMore = this.existNextFeed(feedList, queryFeedDto.limit); if (hasMore) feedList.pop(); const lastId = this.getLastIdFromFeedList(feedList); const newCheckFeedList = await this.checkNewFeeds(feedList); - const result = - FeedPaginationResponseDto.mapToPaginationResponseDtoArray( - newCheckFeedList, - ); - return { result, lastId, hasMore }; + const result = FeedResult.toPaginationResultDtoArray(newCheckFeedList); + return new FeedPaginationResponseDto(result, lastId, hasMore); } private existNextFeed(feedList: FeedView[], limit: number) { @@ -116,7 +118,7 @@ export class FeedService { } } - async searchFeedList(searchFeedReq: SearchFeedReq) { + async searchFeedList(searchFeedReq: SearchFeedRequestDto) { const { find, page, limit, type } = searchFeedReq; const offset = (page - 1) * limit; if (this.validateSearchType(type)) { @@ -130,7 +132,7 @@ export class FeedService { const results = SearchFeedResult.feedsToResults(result); const totalPages = Math.ceil(totalCount / limit); - return new SearchFeedRes(totalCount, results, totalPages, limit); + return new SearchFeedResponseDto(totalCount, results, totalPages, limit); } throw new BadRequestException('검색 타입이 잘못되었습니다.'); } @@ -215,29 +217,32 @@ export class FeedService { async readRecentFeedList() { const redis = this.redisService.redisClient; const recentKeys = await redis.keys(redisKeys.FEED_RECENT_ALL_KEY); - const recentFeedList: FeedPaginationResult[] = []; if (!recentKeys.length) { - return recentFeedList; + return []; } + let recentFeedList: FeedRecentRedis[] = []; const pipeLine = redis.pipeline(); for (const key of recentKeys) { pipeLine.hgetall(key); } const result = await pipeLine.exec(); + recentFeedList.push( - ...result.map(([, feed]: [any, FeedPaginationResult]) => { + ...result.map(([, feed]: [any, FeedRecentRedis]) => { feed.isNew = true; return feed; }), ); - return recentFeedList.sort((currentFeed, nextFeed) => { + recentFeedList = recentFeedList.sort((currentFeed, nextFeed) => { const dateCurrent = new Date(currentFeed.createdAt); const dateNext = new Date(nextFeed.createdAt); return dateNext.getTime() - dateCurrent.getTime(); }); + + return FeedRecentResponseDto.toRecentResponseDtoArray(recentFeedList); } private getIp(request: Request) { diff --git a/server/test/feed/dto/query-feed.dto.spec.ts b/server/test/feed/dto/feed-pagination.dto.spec.ts similarity index 89% rename from server/test/feed/dto/query-feed.dto.spec.ts rename to server/test/feed/dto/feed-pagination.dto.spec.ts index 73654c8..d44d766 100644 --- a/server/test/feed/dto/query-feed.dto.spec.ts +++ b/server/test/feed/dto/feed-pagination.dto.spec.ts @@ -1,12 +1,12 @@ import { validate } from 'class-validator'; -import { QueryFeedDto } from '../../../src/feed/dto/query-feed.dto'; +import { FeedPaginationRequestDto } from '../../../src/feed/dto/request/feed-pagination.dto'; -describe('QueryFeedDto Test', () => { +describe('FeedPaginationRequestDto Test', () => { //given - let queryFeedDto: QueryFeedDto; + let queryFeedDto: FeedPaginationRequestDto; beforeEach(() => { - queryFeedDto = new QueryFeedDto(); + queryFeedDto = new FeedPaginationRequestDto(); }); it('limit에 1보다 작은 값을 입력하면 유효성 검사에 실패한다.', async () => { diff --git a/server/test/feed/dto/query-search.dto.spec.ts b/server/test/feed/dto/search-feed.dto.spec.ts similarity index 92% rename from server/test/feed/dto/query-search.dto.spec.ts rename to server/test/feed/dto/search-feed.dto.spec.ts index 1269f0d..a1c3fb4 100644 --- a/server/test/feed/dto/query-search.dto.spec.ts +++ b/server/test/feed/dto/search-feed.dto.spec.ts @@ -1,15 +1,15 @@ import { - SearchFeedReq, + SearchFeedRequestDto, SearchType, -} from './../../../src/feed/dto/search-feed.dto'; +} from '../../../src/feed/dto/request/search-feed.dto'; import { validate } from 'class-validator'; -describe('SearchFeedReq DTO Test', () => { +describe('SearchFeedRequestDto Test', () => { //given - let searchFeedDto: SearchFeedReq; + let searchFeedDto: SearchFeedRequestDto; beforeEach(() => { - searchFeedDto = new SearchFeedReq({ + searchFeedDto = new SearchFeedRequestDto({ find: 'test', type: SearchType.TITLE, page: 1, From 4364ae96f6fa3583b57ad186e611751b80b3cce8 Mon Sep 17 00:00:00 2001 From: J_Coder Date: Wed, 8 Jan 2025 21:51:15 +0900 Subject: [PATCH 3/7] =?UTF-8?q?=F0=9F=A7=BC=20clean:=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EC=9D=BC=EA=B4=80=EC=84=B1=20=EC=9E=88=EA=B2=8C=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=EB=AA=85=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feed/dto/response/feed-pagination.dto.ts | 12 +++--- server/src/feed/dto/response/recent.dto.ts | 6 +-- .../src/feed/dto/response/search-feed.dto.ts | 35 +++++++++++------ server/src/feed/service/feed.service.ts | 39 +++++++++++-------- 4 files changed, 55 insertions(+), 37 deletions(-) diff --git a/server/src/feed/dto/response/feed-pagination.dto.ts b/server/src/feed/dto/response/feed-pagination.dto.ts index 7ac667a..2209fa8 100644 --- a/server/src/feed/dto/response/feed-pagination.dto.ts +++ b/server/src/feed/dto/response/feed-pagination.dto.ts @@ -13,7 +13,7 @@ export class FeedResult { private isNew: boolean, ) {} - private static toPaginationResultDto(feed: FeedPaginationResult) { + private static toResultDto(feed: FeedPaginationResult) { return new FeedResult( feed.feedId, feed.blogName, @@ -27,8 +27,8 @@ export class FeedResult { ); } - public static toPaginationResultDtoArray(feedList: FeedPaginationResult[]) { - return feedList.map(this.toPaginationResultDto); + public static toResultDtoArray(feedList: FeedPaginationResult[]) { + return feedList.map(this.toResultDto); } } @@ -54,7 +54,7 @@ export class FeedTrendResponseDto { private viewCount: number, ) {} - private static toFeedTrendResponseDto(feed: FeedView) { + private static toResponseDto(feed: FeedView) { return new FeedTrendResponseDto( feed.feedId, feed.blogName, @@ -67,7 +67,7 @@ export class FeedTrendResponseDto { ); } - public static toFeedTrendResponseDtoArray(FeedList: FeedView[]) { - return FeedList.map(this.toFeedTrendResponseDto); + public static toResponseDtoArray(FeedList: FeedView[]) { + return FeedList.map(this.toResponseDto); } } diff --git a/server/src/feed/dto/response/recent.dto.ts b/server/src/feed/dto/response/recent.dto.ts index 1efb259..bd666c8 100644 --- a/server/src/feed/dto/response/recent.dto.ts +++ b/server/src/feed/dto/response/recent.dto.ts @@ -11,7 +11,7 @@ export class FeedRecentResponseDto { private isNew: boolean, ) {} - static toRecentResponseDto(feed: FeedRecentRedis) { + static toResponseDto(feed: FeedRecentRedis) { return new FeedRecentResponseDto( feed.id, feed.blogName, @@ -25,8 +25,8 @@ export class FeedRecentResponseDto { ); } - static toRecentResponseDtoArray(feeds: FeedRecentRedis[]) { - return feeds.map(this.toRecentResponseDto); + static toResponseDtoArray(feeds: FeedRecentRedis[]) { + return feeds.map(this.toResponseDto); } } diff --git a/server/src/feed/dto/response/search-feed.dto.ts b/server/src/feed/dto/response/search-feed.dto.ts index e5fb892..58eb380 100644 --- a/server/src/feed/dto/response/search-feed.dto.ts +++ b/server/src/feed/dto/response/search-feed.dto.ts @@ -1,7 +1,7 @@ import { Feed } from '../../entity/feed.entity'; export class SearchFeedResult { - constructor( + private constructor( private id: number, private blogName: string, private title: string, @@ -9,24 +9,35 @@ export class SearchFeedResult { private createdAt: Date, ) {} - static feedsToResults(feeds: Feed[]): SearchFeedResult[] { - return feeds.map((item) => { - return new SearchFeedResult( - item.id, - item.blog.name, - item.title, - item.path, - item.createdAt, - ); - }); + static toResultDto(feed: Feed) { + return new SearchFeedResult( + feed.id, + feed.blog.name, + feed.title, + feed.path, + feed.createdAt, + ); + } + + static toResultDtoArray(feeds: Feed[]) { + return feeds.map(this.toResultDto); } } export class SearchFeedResponseDto { - constructor( + private constructor( private totalCount: number, private result: SearchFeedResult[], private totalPages: number, private limit: number, ) {} + + static toResponseDto( + totalCount: number, + feeds: SearchFeedResult[], + totalPages: number, + limit: number, + ) { + return new SearchFeedResponseDto(totalCount, feeds, totalPages, limit); + } } diff --git a/server/src/feed/service/feed.service.ts b/server/src/feed/service/feed.service.ts index fb1f835..ca4c01e 100644 --- a/server/src/feed/service/feed.service.ts +++ b/server/src/feed/service/feed.service.ts @@ -48,7 +48,7 @@ export class FeedService { if (hasMore) feedList.pop(); const lastId = this.getLastIdFromFeedList(feedList); const newCheckFeedList = await this.checkNewFeeds(feedList); - const result = FeedResult.toPaginationResultDtoArray(newCheckFeedList); + const result = FeedResult.toResultDtoArray(newCheckFeedList); return new FeedPaginationResponseDto(result, lastId, hasMore); } @@ -87,7 +87,7 @@ export class FeedService { this.feedViewRepository.findFeedById(parseInt(feedId)), ), ); - return FeedTrendResponseDto.toFeedTrendResponseDtoArray( + return FeedTrendResponseDto.toResponseDtoArray( trendFeeds.filter((feed) => feed !== null), ); } @@ -121,20 +121,27 @@ export class FeedService { async searchFeedList(searchFeedReq: SearchFeedRequestDto) { const { find, page, limit, type } = searchFeedReq; const offset = (page - 1) * limit; - if (this.validateSearchType(type)) { - const [result, totalCount] = await this.feedRepository.searchFeedList( - find, - limit, - type, - offset, - ); - - const results = SearchFeedResult.feedsToResults(result); - const totalPages = Math.ceil(totalCount / limit); - - return new SearchFeedResponseDto(totalCount, results, totalPages, limit); + + if (!this.validateSearchType(type)) { + throw new BadRequestException('검색 타입이 잘못되었습니다.'); } - throw new BadRequestException('검색 타입이 잘못되었습니다.'); + + const [result, totalCount] = await this.feedRepository.searchFeedList( + find, + limit, + type, + offset, + ); + + const feeds = SearchFeedResult.toResultDtoArray(result); + const totalPages = Math.ceil(totalCount / limit); + + return SearchFeedResponseDto.toResponseDto( + totalCount, + feeds, + totalPages, + limit, + ); } private validateSearchType(type: string) { @@ -242,7 +249,7 @@ export class FeedService { return dateNext.getTime() - dateCurrent.getTime(); }); - return FeedRecentResponseDto.toRecentResponseDtoArray(recentFeedList); + return FeedRecentResponseDto.toResponseDtoArray(recentFeedList); } private getIp(request: Request) { From 12db81ab29a5ee5f807d9d6ced3ee6f8262e276b Mon Sep 17 00:00:00 2001 From: J_Coder Date: Wed, 8 Jan 2025 21:53:57 +0900 Subject: [PATCH 4/7] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor:=20rss=20dto?= =?UTF-8?q?=20request/response=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/src/rss/controller/rss.controller.ts | 20 +++++++------- .../dto/{ => request}/rss-management.dto.ts | 2 +- .../rss/dto/{ => request}/rss-register.dto.ts | 8 +++--- .../rss/dto/{ => request}/rss-reject.dto.ts | 2 +- .../dto/response/rss-accept-history.dto.ts | 27 +++++++++++++++++++ server/src/rss/dto/response/rss-all.dto.ts | 25 +++++++++++++++++ .../dto/response/rss-reject-history.dto.ts | 27 +++++++++++++++++++ server/src/rss/repository/rss.repository.ts | 4 +-- server/src/rss/service/rss.service.ts | 16 +++++++---- .../test/rss/dto/rss-management.dto.spec.ts | 4 +-- server/test/rss/dto/rss-register.dto.spec.ts | 6 ++--- server/test/rss/e2e/reject.e2e-spec.ts | 6 ++--- server/test/rss/e2e/rss.e2e-spec.ts | 12 ++++++--- 13 files changed, 123 insertions(+), 36 deletions(-) rename server/src/rss/dto/{ => request}/rss-management.dto.ts (82%) rename server/src/rss/dto/{ => request}/rss-register.dto.ts (89%) rename server/src/rss/dto/{ => request}/rss-reject.dto.ts (93%) create mode 100644 server/src/rss/dto/response/rss-accept-history.dto.ts create mode 100644 server/src/rss/dto/response/rss-all.dto.ts create mode 100644 server/src/rss/dto/response/rss-reject-history.dto.ts diff --git a/server/src/rss/controller/rss.controller.ts b/server/src/rss/controller/rss.controller.ts index ab42fcb..4dbd1db 100644 --- a/server/src/rss/controller/rss.controller.ts +++ b/server/src/rss/controller/rss.controller.ts @@ -13,10 +13,10 @@ import { import { CookieAuthGuard } from '../../common/guard/auth.guard'; import { ApiTags } from '@nestjs/swagger'; import { RssService } from '../service/rss.service'; -import { RssRegisterDto } from '../dto/rss-register.dto'; +import { RssRegisterRequestDto } from '../dto/request/rss-register.dto'; import { ApiResponse } from '../../common/response/common.response'; -import { RejectRssDto } from '../dto/rss-reject.dto'; -import { RssManagementDto } from '../dto/rss-management.dto'; +import { RejectRssRequestDto } from '../dto/request/rss-reject.dto'; +import { RssManagementRequestDto } from '../dto/request/rss-management.dto'; import { ApiCreateRss } from '../api-docs/createRss.api-docs'; import { ApiAcceptRss } from '../api-docs/acceptRss.api-docs'; import { ApiReadAcceptHistory } from '../api-docs/readAcceptHistoryRss.api-docs'; @@ -32,7 +32,7 @@ export class RssController { @ApiCreateRss() @Post() @UsePipes(ValidationPipe) - async createRss(@Body() rssRegisterDto: RssRegisterDto) { + async createRss(@Body() rssRegisterDto: RssRegisterRequestDto) { await this.rssService.createRss(rssRegisterDto); return ApiResponse.responseWithNoContent('신청이 완료되었습니다.'); } @@ -52,7 +52,7 @@ export class RssController { @UsePipes(new ValidationPipe({ transform: true })) @Post('accept/:id') @HttpCode(201) - async acceptRss(@Param() params: RssManagementDto) { + async acceptRss(@Param() params: RssManagementRequestDto) { const { id } = params; await this.rssService.acceptRss(id); return ApiResponse.responseWithNoContent('승인이 완료되었습니다.'); @@ -64,8 +64,8 @@ export class RssController { @Post('reject/:id') @HttpCode(201) async rejectRss( - @Body() body: RejectRssDto, - @Param() params: RssManagementDto, + @Body() body: RejectRssRequestDto, + @Param() params: RssManagementRequestDto, ) { const { id } = params; await this.rssService.rejectRss(id, body.description); @@ -76,10 +76,9 @@ export class RssController { @UseGuards(CookieAuthGuard) @Get('history/accept') async readAcceptHistory() { - const rssAcceptHistory = await this.rssService.readAcceptHistory(); return ApiResponse.responseWithData( '승인 기록 조회가 완료되었습니다.', - rssAcceptHistory, + await this.rssService.readAcceptHistory(), ); } @@ -87,10 +86,9 @@ export class RssController { @UseGuards(CookieAuthGuard) @Get('history/reject') async readRejectHistory() { - const rssRejectHistory = await this.rssService.readRejectHistory(); return ApiResponse.responseWithData( 'RSS 거절 기록을 조회하였습니다.', - rssRejectHistory, + await this.rssService.readRejectHistory(), ); } } diff --git a/server/src/rss/dto/rss-management.dto.ts b/server/src/rss/dto/request/rss-management.dto.ts similarity index 82% rename from server/src/rss/dto/rss-management.dto.ts rename to server/src/rss/dto/request/rss-management.dto.ts index 7943327..c204f25 100644 --- a/server/src/rss/dto/rss-management.dto.ts +++ b/server/src/rss/dto/request/rss-management.dto.ts @@ -1,7 +1,7 @@ import { IsInt } from 'class-validator'; import { Type } from 'class-transformer'; -export class RssManagementDto { +export class RssManagementRequestDto { @IsInt({ message: '정수를 입력해주세요.', }) diff --git a/server/src/rss/dto/rss-register.dto.ts b/server/src/rss/dto/request/rss-register.dto.ts similarity index 89% rename from server/src/rss/dto/rss-register.dto.ts rename to server/src/rss/dto/request/rss-register.dto.ts index 4cfdfcd..9e92cf1 100644 --- a/server/src/rss/dto/rss-register.dto.ts +++ b/server/src/rss/dto/request/rss-register.dto.ts @@ -1,8 +1,8 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEmail, IsNotEmpty, IsString, IsUrl, Length } from 'class-validator'; -import { RssInformation } from '../entity/rss.entity'; +import { RssInformation } from '../../entity/rss.entity'; -export class RssRegisterDto { +export class RssRegisterRequestDto { @ApiProperty({ example: 'seok3765.log', description: '블로그 이름을 입력해주세요.', @@ -61,12 +61,12 @@ export class RssRegisterDto { }) rssUrl: string; - constructor(partial: Partial) { + constructor(partial: Partial) { Object.assign(this, partial); } static from(rss: RssInformation) { - return new RssRegisterDto({ + return new RssRegisterRequestDto({ blog: rss.name, name: rss.userName, email: rss.email, diff --git a/server/src/rss/dto/rss-reject.dto.ts b/server/src/rss/dto/request/rss-reject.dto.ts similarity index 93% rename from server/src/rss/dto/rss-reject.dto.ts rename to server/src/rss/dto/request/rss-reject.dto.ts index db7175a..f25ca62 100644 --- a/server/src/rss/dto/rss-reject.dto.ts +++ b/server/src/rss/dto/request/rss-reject.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsNotEmpty, IsString } from 'class-validator'; -export class RejectRssDto { +export class RejectRssRequestDto { @ApiProperty({ example: '거부 사유', description: '거부 사유를 입력해주세요.', diff --git a/server/src/rss/dto/response/rss-accept-history.dto.ts b/server/src/rss/dto/response/rss-accept-history.dto.ts new file mode 100644 index 0000000..bdf496e --- /dev/null +++ b/server/src/rss/dto/response/rss-accept-history.dto.ts @@ -0,0 +1,27 @@ +import { RssAccept } from '../../entity/rss.entity'; + +export class RssAcceptHistoryResponseDto { + private constructor( + private id: number, + private name: string, + private userName: string, + private email: string, + private rssUrl: string, + private blogPlatform: string, + ) {} + + static toResponseDto(rssAccept: RssAccept) { + return new RssAcceptHistoryResponseDto( + rssAccept.id, + rssAccept.name, + rssAccept.userName, + rssAccept.email, + rssAccept.rssUrl, + rssAccept.blogPlatform, + ); + } + + static toResponseDtoArray(rssAcceptList: RssAccept[]) { + return rssAcceptList.map(this.toResponseDto); + } +} diff --git a/server/src/rss/dto/response/rss-all.dto.ts b/server/src/rss/dto/response/rss-all.dto.ts new file mode 100644 index 0000000..3eaf221 --- /dev/null +++ b/server/src/rss/dto/response/rss-all.dto.ts @@ -0,0 +1,25 @@ +import { Rss } from '../../entity/rss.entity'; + +export class RssReadResponseDto { + private constructor( + private id: number, + private name: string, + private userName: string, + private email: string, + private rssUrl: string, + ) {} + + static toResponseDto(rss: Rss) { + return new RssReadResponseDto( + rss.id, + rss.name, + rss.userName, + rss.email, + rss.rssUrl, + ); + } + + static toResponseDtoArray(rssList: Rss[]) { + return rssList.map(this.toResponseDto); + } +} diff --git a/server/src/rss/dto/response/rss-reject-history.dto.ts b/server/src/rss/dto/response/rss-reject-history.dto.ts new file mode 100644 index 0000000..1a7974c --- /dev/null +++ b/server/src/rss/dto/response/rss-reject-history.dto.ts @@ -0,0 +1,27 @@ +import { RssReject } from '../../entity/rss.entity'; + +export class RssRejectHistoryResponseDto { + private constructor( + private id: number, + private name: string, + private userName: string, + private email: string, + private rssUrl: string, + private description: string, + ) {} + + static toResponseDto(rssReject: RssReject) { + return new RssRejectHistoryResponseDto( + rssReject.id, + rssReject.name, + rssReject.userName, + rssReject.email, + rssReject.rssUrl, + rssReject.description, + ); + } + + static toResponseDtoArray(rssRejectList: RssReject[]) { + return rssRejectList.map(this.toResponseDto); + } +} diff --git a/server/src/rss/repository/rss.repository.ts b/server/src/rss/repository/rss.repository.ts index e0cac51..9165815 100644 --- a/server/src/rss/repository/rss.repository.ts +++ b/server/src/rss/repository/rss.repository.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { DataSource, Repository } from 'typeorm'; import { Rss, RssAccept, RssReject } from '../entity/rss.entity'; -import { RssRegisterDto } from '../dto/rss-register.dto'; +import { RssRegisterRequestDto } from '../dto/request/rss-register.dto'; @Injectable() export class RssRepository extends Repository { @@ -9,7 +9,7 @@ export class RssRepository extends Repository { super(Rss, dataSource.createEntityManager()); } - async insertNewRss(rssRegisterDto: RssRegisterDto) { + async insertNewRss(rssRegisterDto: RssRegisterRequestDto) { const { blog, name, email, rssUrl } = rssRegisterDto; const rssObj = this.create({ name: blog, diff --git a/server/src/rss/service/rss.service.ts b/server/src/rss/service/rss.service.ts index 13f1f79..259dd45 100644 --- a/server/src/rss/service/rss.service.ts +++ b/server/src/rss/service/rss.service.ts @@ -8,11 +8,14 @@ import { RssRepository, RssAcceptRepository, } from '../repository/rss.repository'; -import { RssRegisterDto } from '../dto/rss-register.dto'; +import { RssRegisterRequestDto } from '../dto/request/rss-register.dto'; import { EmailService } from '../../common/email/email.service'; import { DataSource } from 'typeorm'; import { Rss, RssReject, RssAccept } from '../entity/rss.entity'; import { FeedCrawlerService } from './feed-crawler.service'; +import { RssReadResponseDto } from '../dto/response/rss-all.dto'; +import { RssAcceptHistoryResponseDto } from '../dto/response/rss-accept-history.dto'; +import { RssRejectHistoryResponseDto } from '../dto/response/rss-reject-history.dto'; @Injectable() export class RssService { @@ -25,7 +28,7 @@ export class RssService { private readonly feedCrawlerService: FeedCrawlerService, ) {} - async createRss(rssRegisterDto: RssRegisterDto) { + async createRss(rssRegisterDto: RssRegisterRequestDto) { const [alreadyURLRss, alreadyURLBlog] = await Promise.all([ this.rssRepository.findOne({ where: { @@ -51,7 +54,8 @@ export class RssService { } async readAllRss() { - return await this.rssRepository.find(); + const rssList = await this.rssRepository.find(); + return RssReadResponseDto.toResponseDtoArray(rssList); } async acceptRss(id: number) { @@ -105,19 +109,21 @@ export class RssService { } async readAcceptHistory() { - return await this.rssAcceptRepository.find({ + const acceptRssList = await this.rssAcceptRepository.find({ order: { id: 'DESC', }, }); + return RssAcceptHistoryResponseDto.toResponseDtoArray(acceptRssList); } async readRejectHistory() { - return await this.rssRejectRepository.find({ + const rejectRssList = await this.rssRejectRepository.find({ order: { id: 'DESC', }, }); + return RssRejectHistoryResponseDto.toResponseDtoArray(rejectRssList); } private identifyPlatformFromRssUrl(rssUrl: string) { diff --git a/server/test/rss/dto/rss-management.dto.spec.ts b/server/test/rss/dto/rss-management.dto.spec.ts index 33c0cb8..4fef806 100644 --- a/server/test/rss/dto/rss-management.dto.spec.ts +++ b/server/test/rss/dto/rss-management.dto.spec.ts @@ -1,11 +1,11 @@ import 'reflect-metadata'; import { validate } from 'class-validator'; -import { RssManagementDto } from '../../../src/rss/dto/rss-management.dto'; +import { RssManagementRequestDto } from '../../../src/rss/dto/request/rss-management.dto'; describe('RssManagementDto Test', () => { it('Rss관리 API의 PathVariable이 정수가 아닐 경우', async () => { // given - const dto = new RssManagementDto(); + const dto = new RssManagementRequestDto(); dto.id = 'abc' as any; // when diff --git a/server/test/rss/dto/rss-register.dto.spec.ts b/server/test/rss/dto/rss-register.dto.spec.ts index 51bffc2..afd34f4 100644 --- a/server/test/rss/dto/rss-register.dto.spec.ts +++ b/server/test/rss/dto/rss-register.dto.spec.ts @@ -1,11 +1,11 @@ import { validate } from 'class-validator'; -import { RssRegisterDto } from '../../../src/rss/dto/rss-register.dto'; +import { RssRegisterRequestDto } from '../../../src/rss/dto/request/rss-register.dto'; describe('RssRegisterDto Test', () => { - let dto: RssRegisterDto; + let dto: RssRegisterRequestDto; beforeEach(() => { - dto = new RssRegisterDto({ + dto = new RssRegisterRequestDto({ blog: 'test', name: 'test', email: 'test@test.com', diff --git a/server/test/rss/e2e/reject.e2e-spec.ts b/server/test/rss/e2e/reject.e2e-spec.ts index 12769d5..955670d 100644 --- a/server/test/rss/e2e/reject.e2e-spec.ts +++ b/server/test/rss/e2e/reject.e2e-spec.ts @@ -4,7 +4,7 @@ import { Repository } from 'typeorm'; import { Rss, RssReject } from '../../../src/rss/entity/rss.entity'; import { RssFixture } from '../../fixture/rss.fixture'; import { RedisService } from '../../../src/common/redis/redis.service'; -import { RejectRssDto } from '../../../src/rss/dto/rss-reject.dto'; +import { RejectRssRequestDto } from '../../../src/rss/dto/request/rss-reject.dto'; import { RssRejectRepository, RssRepository, @@ -37,7 +37,7 @@ describe('Rss Reject E2E Test', () => { const REJECT_REASON = '거절 사유'; const rssFixture = RssFixture.createRssFixture(); const rss = await rssRepository.save(rssFixture); - const rejectRssDto = new RejectRssDto(REJECT_REASON); + const rejectRssDto = new RejectRssRequestDto(REJECT_REASON); // when const response = await request(app.getHttpServer()) @@ -59,7 +59,7 @@ describe('Rss Reject E2E Test', () => { it('존재하지 않는 rss를 거절할 때', async () => { // given const REJECT_REASON = '거절 사유'; - const rejectRssDto = new RejectRssDto(REJECT_REASON); + const rejectRssDto = new RejectRssRequestDto(REJECT_REASON); // when const response = await request(app.getHttpServer()) diff --git a/server/test/rss/e2e/rss.e2e-spec.ts b/server/test/rss/e2e/rss.e2e-spec.ts index c545609..7b8fd98 100644 --- a/server/test/rss/e2e/rss.e2e-spec.ts +++ b/server/test/rss/e2e/rss.e2e-spec.ts @@ -1,5 +1,5 @@ import { INestApplication } from '@nestjs/common'; -import { RssRegisterDto } from '../../../src/rss/dto/rss-register.dto'; +import { RssRegisterRequestDto } from '../../../src/rss/dto/request/rss-register.dto'; import * as request from 'supertest'; import { Repository } from 'typeorm'; import { Rss, RssAccept } from '../../../src/rss/entity/rss.entity'; @@ -28,7 +28,9 @@ describe('/api/rss E2E Test', () => { describe('POST /api/rss E2E Test', () => { it('정상적인 요청이 들어왔다면 올바른 응답을 한다.', async () => { // given - const requestDto = RssRegisterDto.from(RssFixture.createRssFixture()); + const requestDto = RssRegisterRequestDto.from( + RssFixture.createRssFixture(), + ); // when const response = await request(app.getHttpServer()) @@ -41,7 +43,9 @@ describe('/api/rss E2E Test', () => { it('이미 신청한 RSS를 또 신청한다면 거부를 한다.', async () => { // given - const requestDto = RssRegisterDto.from(RssFixture.createRssFixture()); + const requestDto = RssRegisterRequestDto.from( + RssFixture.createRssFixture(), + ); await request(app.getHttpServer()).post('/api/rss').send(requestDto); // when @@ -58,7 +62,7 @@ describe('/api/rss E2E Test', () => { const acceptedRss = await rssAcceptRepository.save( RssAcceptFixture.createRssAcceptFixture(), ); - const rssRegisterDto = RssRegisterDto.from(acceptedRss); + const rssRegisterDto = RssRegisterRequestDto.from(acceptedRss); // when const response = await request(app.getHttpServer()) From 0c0a4719c3b2c203e406a2fccfd3f458a1ef3287 Mon Sep 17 00:00:00 2001 From: J_Coder Date: Wed, 8 Jan 2025 22:20:56 +0900 Subject: [PATCH 5/7] =?UTF-8?q?=F0=9F=A7=BC=20clean:=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EC=9D=BC=EA=B4=80=EC=84=B1=20=EC=9E=88=EA=B2=8C=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=EB=AA=85=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/src/feed/dto/response/feed-pagination.dto.ts | 6 +++++- server/src/feed/dto/response/recent.dto.ts | 2 +- server/src/feed/service/feed.service.ts | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/server/src/feed/dto/response/feed-pagination.dto.ts b/server/src/feed/dto/response/feed-pagination.dto.ts index 2209fa8..3c7dff6 100644 --- a/server/src/feed/dto/response/feed-pagination.dto.ts +++ b/server/src/feed/dto/response/feed-pagination.dto.ts @@ -33,11 +33,15 @@ export class FeedResult { } export class FeedPaginationResponseDto { - constructor( + private constructor( private result: FeedResult[], private lastId: number, private hasMore: boolean, ) {} + + static toResponseDto(result: FeedResult[], lastId: number, hasMore: boolean) { + return new FeedPaginationResponseDto(result, lastId, hasMore); + } } export type FeedPaginationResult = FeedView & { isNew: boolean }; diff --git a/server/src/feed/dto/response/recent.dto.ts b/server/src/feed/dto/response/recent.dto.ts index bd666c8..386b50e 100644 --- a/server/src/feed/dto/response/recent.dto.ts +++ b/server/src/feed/dto/response/recent.dto.ts @@ -1,5 +1,5 @@ export class FeedRecentResponseDto { - constructor( + private constructor( private id: number, private author: string, private blogPlatform: string, diff --git a/server/src/feed/service/feed.service.ts b/server/src/feed/service/feed.service.ts index ca4c01e..d648fb9 100644 --- a/server/src/feed/service/feed.service.ts +++ b/server/src/feed/service/feed.service.ts @@ -49,7 +49,7 @@ export class FeedService { const lastId = this.getLastIdFromFeedList(feedList); const newCheckFeedList = await this.checkNewFeeds(feedList); const result = FeedResult.toResultDtoArray(newCheckFeedList); - return new FeedPaginationResponseDto(result, lastId, hasMore); + return FeedPaginationResponseDto.toResponseDto(result, lastId, hasMore); } private existNextFeed(feedList: FeedView[], limit: number) { From eedba31a860f06d50ae72652c5878e0500d443c3 Mon Sep 17 00:00:00 2001 From: J_Coder Date: Wed, 8 Jan 2025 22:59:57 +0900 Subject: [PATCH 6/7] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor:=20statistic?= =?UTF-8?q?=20dto=20request/response=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/src/rss/repository/rss.repository.ts | 2 +- .../controller/statistic.controller.ts | 6 ++--- .../statistic/dto/platform-response.dto.ts | 16 -------------- .../dto/{ => request}/statistic-query.dto.ts | 2 +- .../dto/response/all-view-count.dto.ts | 17 ++++++++++++++ .../statistic/dto/response/platform.dto.ts | 22 +++++++++++++++++++ .../src/statistic/dto/response/today.dto.ts | 21 ++++++++++++++++++ .../statistic/service/statistic.service.ts | 14 +++++++----- .../statistic/dto/statistic-query.dto.spec.ts | 8 +++---- 9 files changed, 78 insertions(+), 30 deletions(-) delete mode 100644 server/src/statistic/dto/platform-response.dto.ts rename server/src/statistic/dto/{ => request}/statistic-query.dto.ts (92%) create mode 100644 server/src/statistic/dto/response/all-view-count.dto.ts create mode 100644 server/src/statistic/dto/response/platform.dto.ts create mode 100644 server/src/statistic/dto/response/today.dto.ts diff --git a/server/src/rss/repository/rss.repository.ts b/server/src/rss/repository/rss.repository.ts index 9165815..088dfd5 100644 --- a/server/src/rss/repository/rss.repository.ts +++ b/server/src/rss/repository/rss.repository.ts @@ -36,7 +36,7 @@ export class RssAcceptRepository extends Repository { countByBlogPlatform() { return this.createQueryBuilder() - .select(['blog_platform as platform']) + .select('blog_platform', 'platform') .addSelect('COUNT(blog_platform)', 'count') .groupBy('blog_platform') .orderBy('count', 'DESC') diff --git a/server/src/statistic/controller/statistic.controller.ts b/server/src/statistic/controller/statistic.controller.ts index e24c4c9..394a77c 100644 --- a/server/src/statistic/controller/statistic.controller.ts +++ b/server/src/statistic/controller/statistic.controller.ts @@ -8,7 +8,7 @@ import { import { StatisticService } from '../service/statistic.service'; import { ApiResponse } from '../../common/response/common.response'; import { ApiTags } from '@nestjs/swagger'; -import { StatisticQueryDto } from '../dto/statistic-query.dto'; +import { StatisticRequestDto } from '../dto/request/statistic-query.dto'; import { ApiReadPlatformStatistic } from '../api-docs/readPlatformStatistic.api-docs'; import { ApiStatistic } from '../api-docs/statistic.api-docs'; @@ -24,7 +24,7 @@ export class StatisticController { transform: true, }), ) - async readTodayStatistic(@Query() queryObj: StatisticQueryDto) { + async readTodayStatistic(@Query() queryObj: StatisticRequestDto) { const data = await this.statisticService.readTodayStatistic(queryObj.limit); return ApiResponse.responseWithData('금일 조회수 통계 조회 완료', data); } @@ -36,7 +36,7 @@ export class StatisticController { transform: true, }), ) - async readAllStatistic(@Query() queryObj: StatisticQueryDto) { + async readAllStatistic(@Query() queryObj: StatisticRequestDto) { const data = await this.statisticService.readAllStatistic(queryObj.limit); return ApiResponse.responseWithData('전체 조회수 통계 조회 완료', data); } diff --git a/server/src/statistic/dto/platform-response.dto.ts b/server/src/statistic/dto/platform-response.dto.ts deleted file mode 100644 index adced1c..0000000 --- a/server/src/statistic/dto/platform-response.dto.ts +++ /dev/null @@ -1,16 +0,0 @@ -export class PlatformResponseDto { - private constructor( - private platform: string, - private count: number, - ) {} - - static platformToResults(platformStatistics: any[]) { - return platformStatistics.map((platformStatistic) => { - platformStatistic['count'] = parseInt(platformStatistic['count']); - return new PlatformResponseDto( - platformStatistic['platform'], - platformStatistic['count'], - ); - }); - } -} diff --git a/server/src/statistic/dto/statistic-query.dto.ts b/server/src/statistic/dto/request/statistic-query.dto.ts similarity index 92% rename from server/src/statistic/dto/statistic-query.dto.ts rename to server/src/statistic/dto/request/statistic-query.dto.ts index ced27df..2cc026a 100644 --- a/server/src/statistic/dto/statistic-query.dto.ts +++ b/server/src/statistic/dto/request/statistic-query.dto.ts @@ -2,7 +2,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsInt, IsOptional, Min } from 'class-validator'; -export class StatisticQueryDto { +export class StatisticRequestDto { @ApiProperty({ description: '최대로 가져올 데이터 개수를 입력하세요.', }) diff --git a/server/src/statistic/dto/response/all-view-count.dto.ts b/server/src/statistic/dto/response/all-view-count.dto.ts new file mode 100644 index 0000000..b5c2720 --- /dev/null +++ b/server/src/statistic/dto/response/all-view-count.dto.ts @@ -0,0 +1,17 @@ +import { Feed } from '../../../feed/entity/feed.entity'; + +export class StatisticAllResponseDto { + private constructor( + private id: number, + private title: string, + private viewCount: number, + ) {} + + static toResponseDto(feed: Feed) { + return new StatisticAllResponseDto(feed.id, feed.title, feed.viewCount); + } + + static toResponseDtoArray(feeds: Feed[]) { + return feeds.map(this.toResponseDto); + } +} diff --git a/server/src/statistic/dto/response/platform.dto.ts b/server/src/statistic/dto/response/platform.dto.ts new file mode 100644 index 0000000..adac725 --- /dev/null +++ b/server/src/statistic/dto/response/platform.dto.ts @@ -0,0 +1,22 @@ +import { RssAccept } from '../../../rss/entity/rss.entity'; + +export class StatisticPlatformResponseDto { + private constructor( + private platform: string, + private count: number, + ) {} + + static toResponseDto(platformStatistic: RssAccept) { + return new StatisticPlatformResponseDto( + platformStatistic['platform'], + platformStatistic['count'], + ); + } + + static toResponseDtoArray(platformStatistics: RssAccept[]) { + return platformStatistics.map((platformStatistic: RssAccept) => { + platformStatistic['count'] = parseInt(platformStatistic['count']); + return this.toResponseDto(platformStatistic); + }); + } +} diff --git a/server/src/statistic/dto/response/today.dto.ts b/server/src/statistic/dto/response/today.dto.ts new file mode 100644 index 0000000..ca6ab1c --- /dev/null +++ b/server/src/statistic/dto/response/today.dto.ts @@ -0,0 +1,21 @@ +import { Feed } from '../../../feed/entity/feed.entity'; + +export class StatisticTodayResponseDto { + private constructor( + private id: number, + private title: string, + private viewCount: number, + ) {} + + static toResponseDto(todayViewCount: Partial) { + return new StatisticTodayResponseDto( + todayViewCount.id, + todayViewCount.title, + todayViewCount.viewCount, + ); + } + + static toResponseDtoArray(todayViewCountList: Partial[]) { + return todayViewCountList.map(this.toResponseDto); + } +} diff --git a/server/src/statistic/service/statistic.service.ts b/server/src/statistic/service/statistic.service.ts index 0e66505..f1762bf 100644 --- a/server/src/statistic/service/statistic.service.ts +++ b/server/src/statistic/service/statistic.service.ts @@ -1,9 +1,12 @@ +import { StatisticAllResponseDto } from './../dto/response/all-view-count.dto'; import { RssAcceptRepository } from '../../rss/repository/rss.repository'; import { Injectable } from '@nestjs/common'; import { RedisService } from '../../common/redis/redis.service'; import { FeedRepository } from '../../feed/repository/feed.repository'; import { redisKeys } from '../../common/redis/redis.constant'; -import { PlatformResponseDto } from '../dto/platform-response.dto'; +import { StatisticPlatformResponseDto } from '../dto/response/platform.dto'; +import { StatisticTodayResponseDto } from '../dto/response/today.dto'; +import { Feed } from '../../feed/entity/feed.entity'; @Injectable() export class StatisticService { @@ -12,6 +15,7 @@ export class StatisticService { private readonly feedRepository: FeedRepository, private readonly rssAcceptRepository: RssAcceptRepository, ) {} + async readTodayStatistic(limit: number) { const ranking = await this.redisService.redisClient.zrevrange( redisKeys.FEED_TREND_KEY, @@ -19,7 +23,7 @@ export class StatisticService { limit - 1, 'WITHSCORES', ); - const result = []; + const result: Partial[] = []; for (let i = 0; i < ranking.length; i += 2) { const feedId = parseInt(ranking[i]); @@ -37,18 +41,18 @@ export class StatisticService { }); } - return result; + return StatisticTodayResponseDto.toResponseDtoArray(result); } async readAllStatistic(limit: number) { const ranking = await this.feedRepository.findAllStatisticsOrderByViewCount(limit); - return ranking; + return StatisticAllResponseDto.toResponseDtoArray(ranking); } async readPlatformStatistic() { const platformStatistics = await this.rssAcceptRepository.countByBlogPlatform(); - return PlatformResponseDto.platformToResults(platformStatistics); + return StatisticPlatformResponseDto.toResponseDtoArray(platformStatistics); } } diff --git a/server/test/statistic/dto/statistic-query.dto.spec.ts b/server/test/statistic/dto/statistic-query.dto.spec.ts index bef77cb..ceb7391 100644 --- a/server/test/statistic/dto/statistic-query.dto.spec.ts +++ b/server/test/statistic/dto/statistic-query.dto.spec.ts @@ -1,10 +1,10 @@ import { validate } from 'class-validator'; -import { StatisticQueryDto } from '../../../src/statistic/dto/statistic-query.dto'; +import { StatisticRequestDto } from '../../../src/statistic/dto/request/statistic-query.dto'; describe('StatisticQueryDto', () => { it('실수를 입력한다.', async () => { // given - const dto = new StatisticQueryDto(); + const dto = new StatisticRequestDto(); dto.limit = 1.1; // when @@ -19,7 +19,7 @@ describe('StatisticQueryDto', () => { }); it('문자열을 입력한다.', async () => { // given - const dto = new StatisticQueryDto(); + const dto = new StatisticRequestDto(); dto.limit = 'test' as unknown as number; // when @@ -34,7 +34,7 @@ describe('StatisticQueryDto', () => { }); it('음수를 입력한다.', async () => { // given - const dto = new StatisticQueryDto(); + const dto = new StatisticRequestDto(); dto.limit = -1; // when From 384461c14c70e97001ca6cc4c4358b3fcf297ad6 Mon Sep 17 00:00:00 2001 From: J_Coder Date: Thu, 9 Jan 2025 17:23:17 +0900 Subject: [PATCH 7/7] =?UTF-8?q?=F0=9F=90=9B=20fix:=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/src/feed/service/feed.service.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/server/src/feed/service/feed.service.ts b/server/src/feed/service/feed.service.ts index 09afd68..11e9c88 100644 --- a/server/src/feed/service/feed.service.ts +++ b/server/src/feed/service/feed.service.ts @@ -89,7 +89,7 @@ export class FeedService { trendFeeds.filter((feed) => feed !== null), ); } - + async searchFeedList(searchFeedReq: SearchFeedRequestDto) { const { find, page, limit, type } = searchFeedReq; const offset = (page - 1) * limit; @@ -200,10 +200,12 @@ export class FeedService { pipeline.hgetall(key); } }); - - let recentFeedList: FeedPaginationResult[] = result.map(([, feed]:[any, FeedRecentRedis]) => { - return { ...feed, isNew: true }; - }); + + let recentFeedList: FeedRecentRedis[] = result.map( + ([, feed]: [any, FeedRecentRedis]) => { + return { ...feed, isNew: true }; + }, + ); recentFeedList = recentFeedList.sort((currentFeed, nextFeed) => { const dateCurrent = new Date(currentFeed.createdAt);