오늘도 이어서 구현을 해보겠습니다
src/common/interceptors/success.interceptor.ts
import {
Injectable,
NestInterceptor,
ExecutionContext,
CallHandler,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { map, tap } from 'rxjs/operators';
@Injectable()
export class SuccessInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(
map((data) => ({
success: true,
data,
})),
);
}
}
src/common/middlewares/logger.middleware.spec.ts
import { LoggerMiddleware } from './logger.middleware';
describe('LoggerMiddleware', () => {
it('should be defined', () => {
expect(new LoggerMiddleware()).toBeDefined();
});
});
src/common/middlewares/logger.middleware.ts
import { Injectable, Logger, NestMiddleware } from '@nestjs/common';
import { NextFunction, Request, Response } from 'express';
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
private logger = new Logger('HTTP');
use(req: Request, res: Response, next: NextFunction) {
res.on('finish', () => {
this.logger.log(
`${req.ip} ${req.method} ${res.statusCode}`,
req.originalUrl,
);
});
next();
}
}
src/main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';
import { HttpExceptionFilter } from './common/exceptions/http-exception.filter';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe()); //전역 파이프로 설정 : 모든 요청의 유효성 검사
app.useGlobalFilters(new HttpExceptionFilter());
await app.listen(3000);
}
bootstrap();
bootstrap();
src/user/dto/user.dto.ts
import { ApiProperty, PickType } from '@nestjs/swagger';
import { User } from '../schemas/user.schemas';
export class ReadOnlyUserDto extends PickType(User, [
'email',
'name',
] as const) {
@ApiProperty({
example: '3280199',
description: 'id',
})
id: string;
}
src/user/dto/user.request.dto.ts
import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
export class UserRequestDto {
@IsEmail()
@IsNotEmpty()
email: string;
@IsString()
@IsNotEmpty()
password: string;
@IsString()
@IsNotEmpty()
name: string;
}
src/user/schemas/user.schemas.ts
import { Options } from '@nestjs/common';
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
import { Document, SchemaOptions } from 'mongoose';
const options: SchemaOptions = {
timestamps: true,
};
export type UserDocument = User & Document;
@Schema(options)
export class User extends Document {
@Prop({
required: true,
unique: true,
})
@IsEmail()
@IsNotEmpty()
email: string;
@Prop({
required: true,
})
@IsString()
@IsNotEmpty()
name: string;
@Prop({
required: true,
})
@IsString()
@IsNotEmpty()
password: string;
@Prop()
@IsString()
imgUrl: string;
readonly readOnlyData: { id: string; email: string; name: string };
}
export const UserSchema = SchemaFactory.createForClass(User);
src/user/user.controller.ts
import { Body, Get, Post, UseFilters, UseInterceptors } from '@nestjs/common';
import { Controller } from '@nestjs/common';
import { HttpExceptionFilter } from 'src/common/exceptions/http-exception.filter';
import { SuccessInterceptor } from 'src/common/interceptors/success.interceptor';
import { UserService } from './user.service';
import { UserRequestDto } from './dto/user.request.dto';
import { ApiOperation, ApiResponse } from '@nestjs/swagger';
import { ReadOnlyUserDto } from './dto/user.dto';
@Controller('user')
@UseInterceptors(SuccessInterceptor)
@UseFilters(HttpExceptionFilter)
export class UserController {
@ApiOperation({ summary: '현재 유저 가져오기' })
@Get()
getCurrentUser() {
return 'current user';
}
@ApiResponse({
status: 500,
description: 'Server Error...',
})
@ApiResponse({
status: 200,
description: '성공!',
type: ReadOnlyUserDto,
})
@ApiOperation({ summary: '회원가입' })
@Post()
async signUp(@Body() body: UserRequestDto) {
return await this.userService.signUp(body);
}
@ApiOperation({ summary: '로그인' })
@Post('login')
logIn() {
return 'login';
}
@ApiOperation({ summary: '로그아웃' })
@Post('logout')
logOut() {
return 'logout';
}
@ApiOperation({ summary: '고양이 이미지 업로드' })
@Post('upload/cats')
uploadCatImg() {
return 'uploadImg';
}
}
src/user/user.module.ts
import { UserService } from './user.service';
import { MongooseModule } from '@nestjs/mongoose';
import { User, UserSchema } from './schemas/user.schemas';
import { UserRepository } from './user.repository';
@Module({
UserSchema}])], //User모델과 관련된 기능을 수행하는 모듈
imports: [
MongooseModule.forFeature([{ name: User.name, schema: UserSchema }]),
], //User모델과 관련된 기능을 수행하는 모듈
controllers: [UserController],
providers: [UserService, UserRepository],
exports: [UserService],
})
export class UserModule {}
src/user/user.repository.ts
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { User } from './schemas/user.schemas';
import { UserRequestDto } from './dto/user.request.dto';
@Injectable()
export class UserRepository {
constructor(
@InjectModel(User.name) private readonly userModel: Model<User>,
) {}
async existsByEmail(email: string): Promise<boolean> {
const result = await this.userModel.exists({ email });
return Boolean(result);
}
async create(user: UserRequestDto): Promise<User> {
return await this.userModel.create(user);
}
}
오늘도 코드만 고치다 하루가 끝난 거 같습니다
어디가 잘못된 건지 찾는데 너무 어려워서 단계별로 차근차근 다시 해보려고 합니다
내일부터는 강의를 보면서 회원가입부터 다시 시작해보겠습니다 ㅠㅠ
잘 봤습니다. 좋은 글 감사합니다.