// CLI のグローバルインストール
npm i -g @nestjs/cli
// NestJS プロジェクト作成
npx nest new sample-api
// Module
npx nest g mo weapons
// Controller
npx nest g co weapons
// Service
npx nest g s weapons
import { Injectable } from '@nestjs/common';
import { PrismaClient, Weapon } from '@prisma/client';
import {
CreateWeaponDto,
UpdateWeaponDto
} from '../types/dto/weapons.dto';
@Injectable()
export class WeaponsService {
private prisma: PrismaClient;
constructor() {
this.prisma = new PrismaClient();
}
async getAllWeapons(): Promise<Weapon[]> {
return this.prisma.weapon.findMany();
}
async getWeapon(id: number): Promise<Weapon> {
return this.prisma.weapon.findUnique({ where: { id } });
}
async createWeapon(data: CreateWeaponDto): Promise<Weapon> {
return this.prisma.weapon.create({ data });
}
async updateWeapon(id: number, data: UpdateWeaponDto): Promise<Weapon> {
return this.prisma.weapon.update({ where: { id }, data });
}
async deleteWeapon(id: number): Promise<Weapon> {
return this.prisma.weapon.delete({ where: { id } });
}
}
// src/weapons/weapons.controller.ts
import { Body, Controller, Delete, Get, Param, Post, Put } from '@nestjs/common';
import { WeaponsService } from './weapons.service';
import {
CreateWeaponDto,
UpdateWeaponDto,
CreateWeaponResultDto,
UpdateWeaponResultDto
} from '../types/dto/weapons.dto';
import { ApiHeader, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
@ApiTags('weapons')
@Controller('weapons')
export class WeaponsController {
constructor(private readonly weaponsService: WeaponsService) {}
@Get()
@ApiOperation({
operationId: 'Weapons_get',
summary: '武器一覧を取得する',
})
@ApiResponse({
status: 200,
description: 'Success'
})
getAllWeapons() {
return this.weaponsService.getAllWeapons();
}
@Get(':id')
@ApiOperation({
operationId: 'Weapon_get',
summary: '武器を取得する',
})
@ApiResponse({
status: 200,
description: 'Success'
})
getWeapon(@Param('id') id: string) {
return this.weaponsService.getWeapon(+id);
}
@Post()
@ApiOperation({
operationId: 'Weapon_create',
summary: '新規武器を作成する',
})
@ApiResponse({
status: 201,
description: 'Success',
type: CreateWeaponResultDto
})
createWeapon(@Body() weaponData: CreateWeaponDto) {
return this.weaponsService.createWeapon(weaponData);
}
@Put(':id')
@ApiOperation({
operationId: 'Weapon_create',
summary: '武器を更新する',
})
@ApiResponse({
status: 201,
description: 'Success',
type: UpdateWeaponResultDto
})
updateWeapon(@Param('id') id: string, @Body() weaponData: UpdateWeaponDto) {
return this.weaponsService.updateWeapon(+id, weaponData);
}
@Delete(':id')
@ApiOperation({
operationId: 'Weapon_delete',
summary: '武器を削除する',
})
@ApiResponse({
status: 204,
description: 'Success'
})
deleteWeapon(@Param('id') id: string) {
return this.weaponsService.deleteWeapon(+id);
}
}
cd sample-api
yarn add prisma --save-dev
npx prisma init
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
// ER 図の自動生成
generator erd {
provider = "prisma-erd-generator"
theme = "forest"
output = "scheme.md"
}
generator client {
provider = "prisma-client-js"
}
model Weapon {
id Int @id @default(autoincrement())
name String
attackPower Int @map("attack_power")
attribute String
@@map("weapons")
}
model User {
id Int @id @default(autoincrement())
name String
@@map("users")
}
yarn add @prisma/client
npx prisma migrate dev --name init
import * as fs from 'fs';
import { NestFactory } from '@nestjs/core';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { AppModule } from './app.module';
async function bootstrap() {
// (1) アプリケーションのインスタンスを作成する
// 引数に渡しているAppModuleはアプリケーションのルートモジュール
const app = await NestFactory.create(AppModule);
// (2) DocumentBuilderでSwaggerのAPIドキュメントの設定を行う
const config = new DocumentBuilder()
.setTitle('DQ Weapons API')
.setDescription('The DQ Weapons API description')
.setVersion('1.0')
.build();
// (3) SwaggerモジュールにAPIドキュメントを出力させる
const document = SwaggerModule.createDocument(app, config);
// (4) 生成したAPIドキュメンテーションを指定したパス(/api)に公開する
// /apiにアクセスすると、Swagger UIを経由してAPIドキュメンテーションを閲覧できる
SwaggerModule.setup('api', app, document);
// (5) API クライアント用に api-spce ファイルを生成する
fs.writeFileSync(
'src/api-spec/api-spec.json',
JSON.stringify(document, undefined, 2),
);
// (6) NestJSアプリケーションを指定したポートで起動する。ここでは3000
await app.listen(3000);
}
bootstrap();
mkdir src/types/dto
cd src/types/dto
touch weapons.dto.ts
import { ApiProperty } from '@nestjs/swagger';
export class CreateWeaponDto {
@ApiProperty({
description: '名前',
example: 'sword',
required: true,
})
name: string;
@ApiProperty({
description: '威力',
example: 10,
required: true,
})
attackPower: number;
@ApiProperty({
description: '属性',
example: 'normal',
required: true,
})
attribute: string;
}
export class CreateWeaponResultDto {
@ApiProperty({
description: '武器ID',
example: 1,
required: true,
})
id: number;
@ApiProperty({
description: '名前',
example: 'sword',
required: true,
})
name: string;
@ApiProperty({
description: '威力',
example: 10,
required: true,
})
attackPower: number;
@ApiProperty({
description: '属性',
example: 'normal',
required: true,
})
attribute: string;
}
cd src
touch .env
touch docker-compose.yml
version: '3.9'
services:
mysql:
image: mysql:8.0.34
platform: linux/amd64
container_name: mysql-container_dqApi
ports:
- 3307:3306
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: dqApi_develop
DATABASE_URL="mysql://root:root@localhost:3307/dqApi_develop"
docker compose up -d // コンテナの作成
docker-compose exec mysql mysql -hlocalhost -u root -p monap_develop // MySQL の起動
npx prisma migrate dev --name init
NestJS、PrismaとSwaggerでREST APIを開発するチュートリアル【Next.js】PrismaでMySQLローカル環境をDocker構築する方法