diff --git a/nestjs/src/app.module.ts b/nestjs/src/app.module.ts index 8662803..f3b5a97 100644 --- a/nestjs/src/app.module.ts +++ b/nestjs/src/app.module.ts @@ -1,10 +1,24 @@ -import { Module } from '@nestjs/common'; +import { Module, MiddlewareConsumer, RequestMethod } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; - +import { CatsModule } from './cats/cats.module'; +import { logger } from './common/middleware/logger.middleware'; +import { CatsController } from './cats/cats.controller'; +import { MongooseModule } from '@nestjs/mongoose'; +import { TodoModule } from './todo/todo.module'; @Module({ - imports: [], + imports: [CatsModule, MongooseModule.forRoot('mongodb://localhost/nest'), TodoModule], controllers: [AppController], providers: [AppService], }) -export class AppModule {} +export class AppModule { + configure(consumer: MiddlewareConsumer) { + consumer + .apply(logger) + .exclude( + { path: 'cats', method: RequestMethod.GET }, + { path: 'cats', method: RequestMethod.POST }, + ) + .forRoutes(CatsController); + } +} diff --git a/nestjs/src/cats/cats.controller.spec.ts b/nestjs/src/cats/cats.controller.spec.ts new file mode 100644 index 0000000..bdd1191 --- /dev/null +++ b/nestjs/src/cats/cats.controller.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { CatsController } from './cats.controller'; + +describe('CatsController', () => { + let controller: CatsController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [CatsController], + }).compile(); + + controller = module.get(CatsController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/nestjs/src/cats/cats.controller.ts b/nestjs/src/cats/cats.controller.ts new file mode 100644 index 0000000..be27e87 --- /dev/null +++ b/nestjs/src/cats/cats.controller.ts @@ -0,0 +1,65 @@ +import { + Controller, + Get, + Req, + Res, + Post, + Body, + HttpStatus, + HttpException, + ForbiddenException, + Param, + ParseIntPipe, +} from '@nestjs/common'; + +import { CatsService } from './cats.service'; +import { CreateCatDto } from './create-cat.dto'; +import { Cat } from 'src/interfaces/cat.interface'; +import { Query } from '@nestjs/common/decorators'; +import { UsePipes } from '@nestjs/common/decorators/core/use-pipes.decorator'; + +@Controller('cats') +export class CatsController { + constructor(private catsService: CatsService) {} + @Post() + async create(@Body() createCatDto: CreateCatDto) { + this.catsService.create(createCatDto); + } + + @Get(':id') + async findOne( + @Param( + 'id', + new ParseIntPipe({ errorHttpStatusCode: HttpStatus.NOT_ACCEPTABLE }), + ) + id: number, + ) { + return this.catsService.findAll(); + } + // @Get() + // async xxx() { + // try { + // await this.catsService.findAll(); + // } catch (error) { + // throw new HttpException( + // { + // status: HttpStatus.FORBIDDEN, + // error: 'This is a custom message', + // }, + // HttpStatus.FORBIDDEN, + // { + // cause: error, + // }, + // ); + // } + // } + // @Get() + // async findAll() { + // throw new ForbiddenException(); + // } + + // @Get() + // async findAll(): Promise { + // return this.catsService.findAll(); + // } +} diff --git a/nestjs/src/cats/cats.module.ts b/nestjs/src/cats/cats.module.ts new file mode 100644 index 0000000..862e134 --- /dev/null +++ b/nestjs/src/cats/cats.module.ts @@ -0,0 +1,21 @@ +import { Module } from '@nestjs/common'; +import { CatsController } from './cats.controller'; +import { CatsService } from './cats.service'; +import { MongooseModule } from '@nestjs/mongoose'; +import { Cat, CatSchema } from 'src/schemas/cat.schema'; + +@Module({ + imports: [ + MongooseModule.forFeature([ + { + name: Cat.name, + schema: CatSchema, + }, + ]), + ], + controllers: [CatsController], + providers: [CatsService], +}) +export class CatsModule { + constructor(private catsService: CatsService) {} +} diff --git a/nestjs/src/cats/cats.service.spec.ts b/nestjs/src/cats/cats.service.spec.ts new file mode 100644 index 0000000..0e9bf2b --- /dev/null +++ b/nestjs/src/cats/cats.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { CatsService } from './cats.service'; + +describe('CatsService', () => { + let service: CatsService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [CatsService], + }).compile(); + + service = module.get(CatsService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/nestjs/src/cats/cats.service.ts b/nestjs/src/cats/cats.service.ts new file mode 100644 index 0000000..2c2cc95 --- /dev/null +++ b/nestjs/src/cats/cats.service.ts @@ -0,0 +1,16 @@ +import { Injectable } from '@nestjs/common'; +// import { Cat } from 'src/interfaces/cat.interface'; +import { InjectModel } from '@nestjs/mongoose'; +import { Model } from 'mongoose'; +import { Cat, CatDocument } from 'src/schemas/cat.schema'; +import { CreateCatDto } from './create-cat.dto'; + +@Injectable() +export class CatsService { + private readonly cats: Cat[] = []; + async create(createCatDto: CreateCatDto) {} + + findAll(): Cat[] { + return this.cats; + } +} diff --git a/nestjs/src/cats/create-cat.dto.ts b/nestjs/src/cats/create-cat.dto.ts new file mode 100644 index 0000000..8d4d715 --- /dev/null +++ b/nestjs/src/cats/create-cat.dto.ts @@ -0,0 +1,10 @@ +import { IsString, IsInt } from 'class-validator'; + +export class CreateCatDto { + @IsString() + name: string; + @IsInt() + age: number; + @IsString() + breed: string; +} diff --git a/nestjs/src/cats/forbidden.exception.ts b/nestjs/src/cats/forbidden.exception.ts new file mode 100644 index 0000000..a189549 --- /dev/null +++ b/nestjs/src/cats/forbidden.exception.ts @@ -0,0 +1,7 @@ +import { HttpStatus, HttpException } from '@nestjs/common'; + +export class ForbiddenException extends HttpException { + constructor() { + super('Forbidden', HttpStatus.FORBIDDEN); + } +} diff --git a/nestjs/src/common/middleware/logger.middleware.ts b/nestjs/src/common/middleware/logger.middleware.ts new file mode 100644 index 0000000..8c01b66 --- /dev/null +++ b/nestjs/src/common/middleware/logger.middleware.ts @@ -0,0 +1,6 @@ +import { Request, Response, NextFunction } from 'express'; + +export function logger(req: Request, res: Response, next: NextFunction) { + console.log(`Request...`); + next(); +} diff --git a/nestjs/src/interfaces/cat.interface.ts b/nestjs/src/interfaces/cat.interface.ts new file mode 100644 index 0000000..961c973 --- /dev/null +++ b/nestjs/src/interfaces/cat.interface.ts @@ -0,0 +1,5 @@ +export interface Cat { + name: string; + age: number; + breed: string; +} diff --git a/nestjs/src/schemas/cat.schema.ts b/nestjs/src/schemas/cat.schema.ts new file mode 100644 index 0000000..e0b2f0b --- /dev/null +++ b/nestjs/src/schemas/cat.schema.ts @@ -0,0 +1,16 @@ +import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; +import { HydratedDocument } from 'mongoose'; + +export type CatDocument = HydratedDocument; + +@Schema() +export class Cat { + @Prop() + name: string; + @Prop() + age: number; + @Prop() + breed: string; +} + +export const CatSchema = SchemaFactory.createForClass(Cat); diff --git a/nestjs/src/todo/dto/base-todo.dto.ts b/nestjs/src/todo/dto/base-todo.dto.ts new file mode 100644 index 0000000..41ea56e --- /dev/null +++ b/nestjs/src/todo/dto/base-todo.dto.ts @@ -0,0 +1,4 @@ +export class BaseTodoDto { + title: string; + description?: string; +} diff --git a/nestjs/src/todo/dto/create-todo.dto.ts b/nestjs/src/todo/dto/create-todo.dto.ts new file mode 100644 index 0000000..3fdb352 --- /dev/null +++ b/nestjs/src/todo/dto/create-todo.dto.ts @@ -0,0 +1,3 @@ +import { BaseTodoDto } from './base-todo.dto'; + +export class CreateTodoDto extends BaseTodoDto {} diff --git a/nestjs/src/todo/dto/update-todo.dto.ts b/nestjs/src/todo/dto/update-todo.dto.ts new file mode 100644 index 0000000..e4d0915 --- /dev/null +++ b/nestjs/src/todo/dto/update-todo.dto.ts @@ -0,0 +1,5 @@ +import { BaseTodoDto } from './base-todo.dto'; + +export class UpdateTodoDto extends BaseTodoDto { + completedAt: Date; +} diff --git a/nestjs/src/todo/schemas/schema.ts b/nestjs/src/todo/schemas/schema.ts new file mode 100644 index 0000000..50d019c --- /dev/null +++ b/nestjs/src/todo/schemas/schema.ts @@ -0,0 +1,20 @@ +import { Document } from 'mongoose'; +import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; + +export type TodoDocument = Todo & Document; + +@Schema() +export class Todo { + @Prop({ required: true }) + title: string; + @Prop() + description?: string; + @Prop() + completeAt?: Date; + @Prop() + createAt: Date; + @Prop() + deleteAt?: Date; +} + +export const TodoSchema = SchemaFactory.createForClass(Todo); diff --git a/nestjs/src/todo/todo.controller.spec.ts b/nestjs/src/todo/todo.controller.spec.ts new file mode 100644 index 0000000..1925914 --- /dev/null +++ b/nestjs/src/todo/todo.controller.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { TodoController } from './todo.controller'; + +describe('TodoController', () => { + let controller: TodoController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [TodoController], + }).compile(); + + controller = module.get(TodoController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/nestjs/src/todo/todo.controller.ts b/nestjs/src/todo/todo.controller.ts new file mode 100644 index 0000000..b18620f --- /dev/null +++ b/nestjs/src/todo/todo.controller.ts @@ -0,0 +1,37 @@ +import { + Post, + Controller, + Body, + Put, + Delete, + Get, + Param, +} from '@nestjs/common'; +import { UpdateTodoDto } from './dto/update-todo.dto'; +import { CreateTodoDto } from './dto/create-todo.dto'; +import { TodoService } from './todo.service'; + +@Controller('todo') +export class TodoController { + constructor(private readonly service: TodoService) {} + @Get() + async index() { + return await this.service.findAll(); + } + @Get(':id') + async find(@Param('id') id: string) { + return await this.service.findOne(id); + } + @Post() + async create(@Body() createTodoDto: CreateTodoDto) { + return await this.service.create(createTodoDto); + } + @Put(':id') + async update(@Param('id') id: string, @Body() UpdateTodoDto: UpdateTodoDto) { + return await this.service.update(id, UpdateTodoDto); + } + @Delete(':id') + async delete(@Param('id') id: string) { + return await this.service.delete(id); + } +} diff --git a/nestjs/src/todo/todo.module.ts b/nestjs/src/todo/todo.module.ts new file mode 100644 index 0000000..247a4e8 --- /dev/null +++ b/nestjs/src/todo/todo.module.ts @@ -0,0 +1,15 @@ +import { Module } from '@nestjs/common'; +import { TodoService } from './todo.service'; +import { TodoController } from './todo.controller'; +import { Mongoose } from 'mongoose'; +import { MongooseModule, Schema } from '@nestjs/mongoose'; +import { TodoSchema, Todo } from './schemas/schema'; + +@Module({ + providers: [TodoService], + controllers: [TodoController], + imports: [ + MongooseModule.forFeature([{ name: Todo.name, schema: TodoSchema }]), + ], +}) +export class TodoModule {} diff --git a/nestjs/src/todo/todo.service.spec.ts b/nestjs/src/todo/todo.service.spec.ts new file mode 100644 index 0000000..50097b7 --- /dev/null +++ b/nestjs/src/todo/todo.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { TodoService } from './todo.service'; + +describe('TodoService', () => { + let service: TodoService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [TodoService], + }).compile(); + + service = module.get(TodoService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/nestjs/src/todo/todo.service.ts b/nestjs/src/todo/todo.service.ts new file mode 100644 index 0000000..07c3fa4 --- /dev/null +++ b/nestjs/src/todo/todo.service.ts @@ -0,0 +1,36 @@ +import { Injectable } from '@nestjs/common'; +import { InjectModel } from '@nestjs/mongoose'; +import { Model } from 'mongoose'; +import { Todo, TodoDocument } from './schemas/schema'; +import { CreateTodoDto } from './dto/create-todo.dto'; +import { UpdateTodoDto } from './dto/update-todo.dto'; + +@Injectable() +export class TodoService { + constructor( + @InjectModel(Todo.name) private readonly model: Model, + ) {} + + async findAll(): Promise { + return await this.model.find().exec(); + } + + async findOne(id: string): Promise { + return await this.model.findById(id).exec(); + } + + async create(createTodoDto: CreateTodoDto): Promise { + return await new this.model({ + ...createTodoDto, + createdAt: new Date(), + }).save(); + } + + async update(id: string, updateToDto: UpdateTodoDto): Promise { + return await this.model.findByIdAndUpdate(id, updateToDto).exec(); + } + + async delete(id: string): Promise { + return await this.model.findByIdAndDelete(id).exec(); + } +}