😽
はじめてのnest new
目的
仕事でNestJSを使うのですが自分でnest new
したことなかったので学習の意味で簡単なCRUD処理を作成したので、記録と残して置こうと思いキーボードを執りました。
環境
OS:macOS Big Sur 11.1
Node:v14.4.0
NestJS:7.5.4
導入
npm i -g @nestjs/cli
新規プロジェクト作成
nest new nestjs_todo
必要なものを導入
npm i @nestjs/typeorm typeorm mysql2 class-transformer class-validator
ormconfig.jsonを作成
ormconfig.json
{
"name": "default",
"type": "mysql",
"host": "localhost",
"port": 3306,
"username": "root",
"password": "",
"database": "nest",
"synchronize": true,
"logging": true,
"entities": [
"dist/entities/**/*.entity.js"
],
"migrations": [
"dist/migrations/**/*.js"
]
}
エンティティファイル作成
src/entities/task.entity.ts
import {
Entity,
Column,
PrimaryGeneratedColumn,
CreateDateColumn,
UpdateDateColumn,
} from "typeorm";
@Entity()
export class Task {
@PrimaryGeneratedColumn()
readonly id: number;
@Column()
title: string;
@CreateDateColumn()
readonly createdAt?: Date;
@UpdateDateColumn()
readonly updatedAt?: Date;
}
migrationファイル作成
npx typeorm migration:generate -d src/migrations -n create-task
src/migrations/1608641968685-create-task.ts
import {MigrationInterface, QueryRunner} from "typeorm";
export class createTask1608641968685 implements MigrationInterface {
name = 'createTask1608641968685'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query("CREATE TABLE `task` (`id` int NOT NULL AUTO_INCREMENT, `title` varchar(255) NOT NULL, `createdAt` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updatedAt` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), PRIMARY KEY (`id`)) ENGINE=InnoDB");
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query("DROP TABLE `task`");
}
}
migration実行
npx typeorm migration:run
Controller作成
nest g controller tasks
src/tasks/tasks.controller.ts
import { Controller } from '@nestjs/common';
@Controller('tasks')
export class TasksController {}
Service作成
nest g service tasks
src/tasks/tasks.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class TasksService {}
モジュール作成
nest g module tasks
src/tasks/tasks.module.ts
import { Module } from '@nestjs/common';
@Module({})
export class TasksModule {}
Read処理を実装
src/tasks/tasks.controller.ts
import { Controller, Get } from '@nestjs/common';
import { Task } from 'src/entities/task.entity';
import { TasksService } from './tasks.service'
@Controller('tasks')
export class TasksController {
constructor(private readonly taskService: TasksService) {}
@Get()
async findAll(): Promise<Task[]> {
return await this.taskService.findAll()
}
}
src/tasks/tasks.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Task } from 'src/entities/task.entity';
import { TasksController } from './tasks.controller';
import { TasksService } from './tasks.service';
@Module({
controllers: [TasksController],
imports: [TypeOrmModule.forFeature([Task])],
providers: [TasksService],
exports: [TypeOrmModule],
})
export class TasksModule {}
src/tasks/tasks.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Task } from 'src/entities/task.entity';
import { Repository } from 'typeorm';
@Injectable()
export class TasksService {
constructor(
@InjectRepository(Task)
private readonly taskRepository: Repository<Task>
) {}
async findAll(): Promise<Task[]> {
return await this.taskRepository.find()
}
}
Create処理を実装
src/dto/create-task.dto.ts
import { IsNotEmpty, IsString } from "class-validator";
export class CreateTaskDTO {
@IsNotEmpty()
@IsString()
title: string;
}
src/main.ts
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// 追加
app.useGlobalPipes(new ValidationPipe());
await app.listen(3000);
}
bootstrap();
src/tasks/tasks.controller.ts
@Post()
async create(@Body() createTaskDto: CreateTaskDTO) {
return await this.taskService.create(createTaskDto)
}
src/tasks/tasks.service.ts
async create(task: CreateTaskDTO): Promise<InsertResult> {
return await this.taskRepository.insert(task)
}
Update処理を実装
src/dto/update-task.dto.ts
import { IsNotEmpty, IsString } from "class-validator";
export class UpdateTaskDto {
@IsNotEmpty()
@IsString()
title: string;
}
src/tasks/tasks.controller.ts
@Put(':id')
async update(@Param('id') id: string, @Body() updateTaskDto: UpdateTaskDto) {
return await this.taskService.update(+id, updateTaskDto)
}
src/tasks/tasks.service.ts
async update(id: number, updateTaskDto: UpdateTaskDto) {
return await this.taskRepository.update(id, updateTaskDto)
}
Delete処理を実装
src/tasks/tasks.controller.ts
@Delete(':id')
async remove(@Param('id') id: string) {
return this.taskService.remove(+id)
}
src/tasks/tasks.service.ts
async remove(id: number) {
return await this.taskRepository.delete(id)
}
感想
ゼロから自分でやってみるというのはたいへんな部分もありましたが新たな知識を増やすことができました。そして、公式サイトのドキュメントのわかりやすさを再実感しました。
コード全体は下記のリポジトリで確認できるようにしてあります。
参考
Discussion