NestJSとは
NestJSとは、NodeJS環境で動くサーバーサイドアプリケーションフレームワークです。
基本的にTypeScriptでコーディングを行いますが、JavaScriptで書くことも可能です。
Expressをコアに作られているので、Expressの機能は備えつつ、テストフレームワークJestを標準装備していたり、NestCLIを利用して効率良く開発を進めることができたり、多くの機能を搭載しています。
今回は、DockerでPostgreSQLサーバを立ち上げ、NestJSを用いた商品管理のCRUD実装を行なっていこうと思います。
1. NestJSのプロジェクト作成
NestCLIを使用して、NestJSのプロジェクトを立ち上げます。
まずは以下コマンドで、NestCLIがインストールされているか確認します。
nest --version
バージョンが表示されれば、既にインストールされています。command not found
などのエラーが出た場合はNestCLIがインストールされていないので、以下コマンドを実行してください。
npm i -g @nestjs/cli
インストールが完了したら、以下コマンドでNestJSのプロジェクトを立ち上げます。
nest new nest-tutorial
使用するパッケージマネージャーを選べますので、今回はnpmを選択してください
? Which package manager would you ❤️ to use? (Use arrow keys)
❯ npm
yarn
以下のようなログが出れば、NestJSプロジェクトの立ち上げ完了です!👏
Thanks for installing Nest 🙏
Please consider donating to our open collective
to help us maintain this package.
🍷 Donate: https://opencollective.com/nest
2. DB接続(PostgreSQL)
2-1. PostgreSQLのサーバー起動
今回はPostgreSQLを利用します。
Dockerを使用してDBサーバーを立ち上げましょう。
以下Dockerファイルをルートディレクトリに置いてください。
version: '3.7'
services:
postgres:
image: postgres:14.2-alpine
container_name: nest-postgres
ports:
- 5432:5432
volumes:
- ./docker/postgres/init.d:/docker-entrypoint-initdb.d
- ./docker/postgres/pgdata:/var/lib/postgresql/data
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_INITDB_ARGS: "--encoding=UTF-8"
POSTGRES_DB: postgres
hostname: postgres
restart: always
user: root
pgadmin:
image: dpage/pgadmin4
restart: always
ports:
- 81:80
environment:
PGADMIN_DEFAULT_EMAIL: test@test.com
PGADMIN_DEFAULT_PASSWORD: password
volumes:
- ./docker/pgadmin:/var/lib/pgadmin
depends_on:
- postgres
以下コマンドでPostgreSQLのコンテナを立ち上げます。
docker-compose up --build
コンテナが立ち上がったら、ブラウザでlocalhost:81にアクセスしてください。
以下のような画面が表示されれば、正常にPostgreSQLコンテナが立ち上がっています。
メールアドレスとパスワードはそれぞれDockerファイルに記載されてあるPGADMIN_DEFAULT_EMAIL
とPGADMIN_DEFAULT_PASSWORD
の値を入力してください。
ログインできたら、Dashbord
からAdd New Server
を選択し、それぞれ以下の情報を入力してください。
項目 | 入力内容 |
---|---|
Name | nest-js-tutorial |
Host name/address | postgres |
Port | postgres |
Maintenance database | postgres |
Username | postgres |
Password | postgres |
Save
ボタンを押して、以下のような画面が表示されたら、PostgreSQLサーバーの立ち上げが完了
2-2. ORM設定
では、立ち上げたPostgreSQLサーバーと、NestJSを接続していきましょう。
今回は、TypeORMというORMを使用します。
以下コマンドで、TypeORM、PostgreSQLのドライバーをインストールしてください。
npm i --save typeorm@0.2.45 @nestjs/typeorm@8.0.2 pg
ルートモジュール(/src/app.module.ts
)を以下のように編集します。
TypeORMのモジュールをインポートし、forRoot()
メソッドをimports
の中に入れます。
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
TypeOrmModule.forRoot()
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
ルートディレクトリにormconfig.js
を作成し、以下のようなファイルを作成してください。
TypeORMはこのファイルを元にDB接続を行ってくれます。
module.exports = {
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'postgres',
password: 'postgres',
database: 'postgres',
autoLoadEntities: true,
entities: ['dist/entities/*.entity.js'],
migrations: ['dist/migrations/*.js'],
cli: {
entitiesDir: 'src/entities',
migrationsDir: 'src/migrations',
},
};
では、以下のNestCLIコマンドを実行して、実際にNestJSサーバーを立ち上げてみましょう。
npm run start:dev
以下なログが出力されて、エラーログっぽいものがでなければDB接続が完了です!
3. エンティティの作成
エンティティとは、データベースのテーブル毎に作成されるテーブル定義をするものです。
typeorm
モジュールからEntity
デコレーターをインポートして、classに付与することでエンティティクラスを作成することができます。
クラス内で、それぞれtypeorm
モジュールからインポートしたデコレーターを使用して、カラム毎のルールを定義していきます。
import { PrimaryGeneratedColumn, Column, Entity } from 'typeorm';
@Entity()
export class Item {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column()
name: string;
@Column()
price: number;
@Column()
createdAt: string;
@Column()
updatedAt: string;
}
4. マイグレーション実行
マイグレーションをおこなっていきます。
以下のTypeORMのCLIコマンドを使用して、マイグレーションファイルを作成します。
npx typeorm migration:generate -n CreateItemsTable -d src/migrations
実行すると、src/migrations
ディレクトリ配下に、以下のようなファイルが生成されます。
import {MigrationInterface, QueryRunner} from "typeorm";
export class CreateItemsTable1663567364289 implements MigrationInterface {
name = 'CreateItemsTable1663567364289'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`CREATE TABLE "items" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "name" character varying NOT NULL, "price" integer NOT NULL, "createdAt" character varying NOT NULL, "updatedAt" character varying NOT NULL, CONSTRAINT "PK_ba5885359424c15ca6b9e79bcf6" PRIMARY KEY ("id"))`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "items"`);
}
}
他バックエンドのフレームワークに詳しい方は、これからマイグレーションファイルにテーブル定義を記載していくと思われる方も多いかと思いますが、TypeORMでは、紐付くエンティティを見てマイグレーションを行なってくれるので、マイグレーションファイル自体を編集することは基本的にありません。
では、実際にマイグレーションを実行しましょう。
npx typeorm migration:run
以下のようなログが出たら、マイグレーション成功です!
query: SELECT * FROM current_schema()
query: CREATE EXTENSION IF NOT EXISTS "uuid-ossp"
query: SHOW server_version;
query: SELECT * FROM "information_schema"."tables" WHERE "table_schema" = 'public' AND "table_name" = 'migrations'
query: CREATE TABLE "migrations" ("id" SERIAL NOT NULL, "timestamp" bigint NOT NULL, "name" character varying NOT NULL, CONSTRAINT "PK_8c82d7f526340ab734260ea46be" PRIMARY KEY ("id"))
query: SELECT * FROM "information_schema"."tables" WHERE "table_schema" = 'public' AND "table_name" = 'typeorm_metadata'
query: CREATE TABLE "typeorm_metadata" ("type" character varying NOT NULL, "database" character varying, "schema" character varying, "table" character varying, "name" character varying, "value" text)
query: SELECT * FROM "migrations" "migrations" ORDER BY "id" DESC
0 migrations are already loaded in the database.
1 migrations were found in the source code.
1 migrations are new migrations that needs to be executed.
query: START TRANSACTION
query: CREATE TABLE "items" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "name" character varying NOT NULL, "price" integer NOT NULL, "createdAt" character varying NOT NULL, "updatedAt" character varying NOT NULL, CONSTRAINT "PK_ba5885359424c15ca6b9e79bcf6" PRIMARY KEY ("id"))
query: INSERT INTO "migrations"("timestamp", "name") VALUES ($1, $2) -- PARAMETERS: [1663567364289,"CreateItemsTable1663567364289"]
Migration CreateItemsTable1663567364289 has been executed successfully.
query: COMMIT
テーブルが実際に作成されているか、localhost:81にアクセスし、データベースを見てみましょう
横のタブから、postgres
👉Databases(1)
👉Schemas(1)
👉Tables(3)
の順に開くと、データベースのテーブルを見ることができます。
items
テーブルががありますね!
マイグレーションが無事に成功しました!👏
5. モジュール/コントローラー/サービスの作成
NestJSでは、モジュール、サービス、コントローラーの3つで、1つの機能を実装していきます。
5-1. サービス作成
NestCLIコマンドでサービスを作成します。
NestCLIを利用してサービス/コントローラーを作成すると、テストファイルを自動生成してくれます。
今回はテストファイルは必要ないので、--no-spec
オプションを付与して自動生成を無効にします。
nest generate service items --no-spec
srcディレクトリ配下に、itemsディレクトリが自動で作成され、その配下にitems.service.ts
が作成されます。
import { Injectable } from '@nestjs/common';
@Injectable()
export class ItemsService {}
5-2. コントローラー作成
NestCLIコマンドでコントローラーを作成します。
nest generate controller items --no-spec
itemsディレクトリ配下にitems.controller.ts
が作成されます。
コンストラクターで、サービスクラスをDIしておきます。
import { Controller } from '@nestjs/common';
import { ItemsService } from './items.service';
@Controller('items')
export class ItemsController {
constructor (private readonly itemsService: ItemsService) {}
}
5-3. モジュール作成
NestCLIコマンドでモジュールを作成します。
nest generate module items
itemsディレクトリ配下にitems.module.ts
が作成されます。
import { Module } from '@nestjs/common';
import { ItemsController } from './items.controller';
import { ItemsService } from './items.service';
@Module({
controllers: [ItemsController],
providers: [ItemsService]
})
export class ItemsModule {}
5-4. ルートモジュールに登録
ルートモジュール(app.module.ts
)に登録することで追加した機能が使えるようになります。
src/app.module.ts
で作成したitemsモジュールをインポートして、imports
にモジュールクラス追加してください。
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
// モジュールをインポート!
import { ItemsModule } from './items/items.module';
@Module({
imports: [
TypeOrmModule.forRoot(),
// 追加!!
ItemsModule
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
これにて、itemsモジュールの機能が使えるようになりました👏
6. リポジトリの作成
6-1. リポジトリクラスの作成
リポジトリクラスとは、DB操作を実際に行うメソッド群を持つクラスです。
src/items
ディレクトリ配下に、items.repository.ts
ファイルを作成して、以下のように編集します。
import { Items } from 'src/entities/items.entity';
import { EntityRepository, Repository } from 'typeorm';
@EntityRepository(Items)
export class ItemsRepository extends Repository<Items> {}
@EntityRepository()
デコレーターをインポートし、引数に紐付くエンティティを渡します。
Repository
クラスを継承し、TypeORMのメソッド群を使用できるようにし、ジェネリクスに紐付くエンティティを設定します。
6-2. モジュールにリポジトリを登録
モジュール(items.module.ts
)にリポジトリクラスを登録します。
imports
プロパティにTypeOrmModule.forFeature()
メソッドを入れます。
forFeature
の引数に作成したリポジトリクラスを含む配列にを入れます。
これでサービスでリポジトリをDIすることが可能になりました。
import { Module } from '@nestjs/common';
// 追加=============================================
import { TypeOrmModule } from '@nestjs/typeorm';
import { ItemsRepository } from './items.repository';
// ↑↑↑↑============================================
import { ItemsController } from './items.controller';
import { ItemsService } from './items.service';
@Module({
// 追加=============================================
imports: [TypeOrmModule.forFeature([
ItemsRepository
])],
// ↑↑↑↑============================================
controllers: [ItemsController],
providers: [ItemsService]
})
export class ItemsModule {}
6-3. サービスでリポジトリクラスをDI
サービスクラス内でリポジトメソッドを使用できるように、コンストラクタでリポジトリをDIします。
import { Injectable } from '@nestjs/common';
// 追加=============================================
import { ItemsRepository } from './items.repository';
// ↑↑↑↑============================================
@Injectable()
export class ItemsService {
// 追加=============================================
constructor (private readonly itemsRepository: ItemsRepository) {}
// ↑↑↑↑============================================
}
7. DTOの作成
DTOを定義していきます。
DTOとはプロパティ毎の型などを定義したものを集めたオブジェクトで、登録や更新処理を行う際に使います。
更に便利なのが、型定義と同時にバリデーションルールも設定することができます。
バリデーションルールを設定するために、以下のパッケージclass-validator
をインストールしましょう。
npm i --save class-validator
src/items
ディレクトリにdto
ディレクトリを作り、その配下にitem.dto.ts
ファイルを作成します。
それぞれのプロパティの上に、class-validator
からインポートしたデコレーターを使用してバリデーションルールを指定していきます。
こうすることで、リクエスト時にバリデーションルールに引っかかると、エラーが返るようになります。
import { IsNumber, IsString } from 'class-validator';
export class ItemDto {
@IsString() // 文字であること
name: string;
@IsNumber() // 数値であること
price: number;
}
8. 登録機能の作成(CREATE)
8-1. リポジトリの編集
リポジトリに、登録処理を行うメソッドcreateItem
を作成します。
TypeORMメソッドcreate
で新たなデータオブジェクトを作成し、save
で実際にデータベースに保存しています。
データベース操作処理は非同期で行われる為、メソッドの返り値はPromise型にして、ジェネリクスで紐付くエンティティクラスを指定します。
import { EntityRepository, Repository } from 'typeorm';
// 追加=============================================
import { Items } from 'src/entities/items.entity';
import { ItemDto } from './dto/item.dto';
// ↑↑↑↑============================================
@EntityRepository(Items)
export class ItemsRepository extends Repository<Items> {
// 追加=============================================
async createItem (itemDto: ItemDto): Promise<Items> {
const { name, price } = itemDto;
const item = this.create({
name,
price,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
}); // データオブジェクトを作成
await this.save(item); // 実際にDBに登録
return item; // 作成したデータを返す
}
// ↑↑↑↑============================================
}
8-2. サービスの編集
作成したリポジトリメソッドcreateItem
を実行するメソッドを作成します。
引数には、作成したDTO型のオブジェクトを定義しましょう。
import { Injectable } from '@nestjs/common';
import { ItemsRepository } from './items.repository';
// 追加=============================================
import { Items } from 'src/entities/items.entity';
import { ItemDto } from './dto/item.dto';
// ↑↑↑↑============================================
@Injectable()
export class ItemsService {
constructor (private readonly itemsRepository: ItemsRepository) {}
// 追加=============================================
async createItem (itemDto: ItemDto): Promise<Items> {
return await this.itemsRepository.createItem(itemDto);
}
// ↑↑↑↑============================================
}
8-3. コントローラーの編集
最後に、URL/items
にPOSTリクエストがきた場合に、登録処理を行うようにハンドラーメソッドを作成しましょう。
引数は、@Body()
を利用してリクエストボディにアクセスすることができます。
リクエストボディとして渡ってきたItemDto
型のオブジェクトを引数にして、サービスメソッドcreateUser
を実行しましょう。
import { Body, Controller, Post } from '@nestjs/common';
import { ItemsService } from './items.service';
// 追加=============================================
import { Items } from 'src/entities/items.entity';
import { ItemDto } from './dto/item.dto';
// ↑↑↑↑============================================
@Controller('items')
export class ItemsController {
constructor (private readonly itemsService: ItemsService) {}
// 追加=============================================
@Post() // @Post()デコレーターを使用して、POSTリクエストに対するハンドラーを登録
// サービスのcreateItemメソッドを実行するハンドラを定義
// DB操作は非同期処理のため、返り値の型は、Promise。ジェネリクスでItemsエンティティを付与
async createUser (@Body() itemDto: ItemDto): Promise<Items> {
return await this.itemsService.createItem(itemDto);
}
// ↑↑↑↑============================================
}
8-4. 動作確認
Postmanで、作成した登録APIの動作確認をしてみます。
メソッドをPOST
にし、URLをhttp://localhost:3000/items
にします。
Body
タブを選択し、x-www-form-unlencoded
を選択します。
name
とprice
にそれぞれ値を指定し、Send
ボタンを押してAPIを実行します。
以下のようなレスポンスが返って来れば、正常に登録処理が終了しています。
データベースを見てみて、レスポンスとして返ってきたデータが登録されていることが確認できれば、登録APIの実装が完了です!👏
9. 参照機能の作成(READ)
9-1. サービスの編集
全件取得と、一件取得のAPIを実装しましょう。
今回はTypeORMの標準メソッドのfind
とfindOne
を実行すれば全件取得が可能なので、リポジトリの編集はしません。
TypeORMメソッドfind
/findOne
を実行するサービスメソッドをそれぞれ定義します。
全件取得の際は配列形式のレスポンスになる為、Promiseのジェネリクスで指定するエンティティクラスに[]
を付与するのを忘れないでください。
import { Injectable } from '@nestjs/common';
import { Items } from 'src/entities/items.entity';
import { ItemDto } from './dto/item.dto';
import { ItemsRepository } from './items.repository';
@Injectable()
export class ItemsService {
constructor (private readonly itemsRepository: ItemsRepository) {}
// 追加=============================================
// 全件取得
async findAll (): Promise<Items[]> {
return await this.itemsRepository.find();
}
// 1件取得
async findById (id: string): Promise<Items> {
// 引数として渡ってきたidを元に、データベースから検索
const foundItem = await this.itemsRepository.findOne(id);
if (!foundItem) {
throw new NotFoundException(); // データが見つからない場合、例外を投げる
}
return foundItem;
}
// ↑↑↑↑============================================
async createItem (itemDto: ItemDto): Promise<Items> {
return await this.itemsRepository.createItem(itemDto);
}
}
9-2. コントローラーの編集
@Get()
デコレーターで、GETメソッドに対するハンドラーメソッドを作成します。
デコレーターの引数に文字列を付与することで、items/
以降のパスを定義することができます。
:id
とすることで、パスパラメータを定義することができます。
GETメソッドitems/
でリクエストが来た場合は、サービスクラスのfindAll
メソッドを実行するハンドラを定義し、
GETメソッドitems/:id
でリクエストが来た場合は、サービスクラスのfindById
メソッドを実行するハンドラを定義します。
import { Body, Controller, Get, Post } from '@nestjs/common';
import { Items } from 'src/entities/items.entity';
import { ItemsService } from './items.service';
import { ItemDto } from './dto/item.dto'
@Controller('items')
export class ItemsController {
constructor (private readonly itemsService: ItemsService) {}
// 追加=============================================
@Get()
async findAll (): Promise<Items[]> {
return await this.itemsService.findAll();
}
@Get(':id') // "items/"以降のパスを定義。パスパラメータにidを定義
async findById (@Param() id: string): Promise<Items> {
// パスパラメータのidを引数にして、サービスメソッドfindByIdを実行
return await this.itemsService.findById(id);
}
// ↑↑↑↑============================================
@Post()
async createUser (@Body() itemDto: ItemDto): Promise<Items> {
return await this.itemsService.createItem(itemDto);
}
}
9-3. 動作確認
まずは全件取得のAPIのテストをしてみます。
メソッドをGET
にして、URLをhttp://localhost:3000/items
を実行してみます。
以下のように、配列形式で登録済みのデータが返れば、正常に全件取得処理が実行できています👏
1件取得APIのテストをしてみます。
登録済みのデータのうちどれかのデータのid
をコピーして、http://localhost:3000/items/
の末尾にペーストして実行してください。
以下のように、オブジェクト形式でIDが一致する一件のデータが返れば、正常に1件取得処理が実行できています👏
10. 更新機能の作成(UPDATE)
更新APIを実装しましょう。
流れとしては、パスパラメータのIDで取得したデータを、リクエストボディの値に更新するという処理になります。
10-1. サービスの編集
既存のfindById
メソッドを利用して、IDからデータを検索します。
取得できたら、プロパティの値をリクエストボディの値に更新して、更新日を現在日時にします。
save
メソッドを実行してデータベースに反映します。
import { Injectable, NotFoundException } from '@nestjs/common';
import { Items } from 'src/entities/items.entity';
import { ItemDto } from './dto/item.dto';
import { ItemsRepository } from './items.repository';
@Injectable()
export class ItemsService {
constructor (private readonly itemsRepository: ItemsRepository) {}
async findAll (): Promise<Items[]> {
return await this.itemsRepository.find();
}
async findById (id: string): Promise<Items> {
const foundItem = await this.itemsRepository.findOne(id);
if (!foundItem) {
throw new NotFoundException();
}
return foundItem;
}
async createItem (itemDto: ItemDto): Promise<Items> {
return await this.itemsRepository.createItem(itemDto);
}
// 追加=============================================
async updateItem (id: string, itemDto: ItemDto): Promise<Items> {
let foudnItemToUpdate = await this.findById(id); // 更新するデータを取得
foudnItemToUpdate.name = itemDto.name; // nameを更新
foudnItemToUpdate.price = itemDto.price; // priceを更新
foudnItemToUpdate.updatedAt = new Date().toISOString(); // 更新日時を更新
return await this.itemsRepository.save(foudnItemToUpdate); // データ保存
}
// ↑↑↑↑============================================
}
10-2. コントローラーの編集
PATCHメソッドでリクエストを受けた際に、パラメータとリクエストボディを引数にしてサービスメソッドを実行します。
import { Body, Controller, Get, Param, Patch, Post } from '@nestjs/common';
import { Items } from 'src/entities/items.entity';
import { ItemsService } from './items.service';
import { ItemDto } from './dto/item.dto'
@Controller('items')
export class ItemsController {
constructor (private readonly itemsService: ItemsService) {}
@Get()
async findAll (): Promise<Items[]> {
return await this.itemsService.findAll();
}
@Get(':id')
async findById (@Param() id: string): Promise<Items> {
return await this.itemsService.findById(id);
}
@Post()
async createUser (@Body() itemDto: ItemDto): Promise<Items> {
return await this.itemsService.createItem(itemDto);
}
// 追加=============================================
@Patch(':id')
async updateItem (
@Param() id: string,
@Body() itemDto: ItemDto
): Promise<Items> {
return await this.itemsService.updateItem(id, itemDto);
}
// ↑↑↑↑============================================
}
10-3. 動作確認
更新したい既存のデータのid
をコピーします。
メソッドをPATCH
にして、URLをhttp://localhost:3000/items/{コピーしたid}
にします。
リクエストボディに、更新後の値を入れて、APIを実行します。
以下のように、更新後のデータがレスポンスとして返却されれば、APIが正常終了しています。
メソッドをGET
にして、URLをhttp://localhost:3000/items/{コピーしたid}
で1件取得APIを実行し、データが更新されていることが確認できれば、更新APIの実装が完了です!👏
11. 削除機能の作成(DELETE)
11-1. サービスの編集
TypeORMのdelete
メソッドを実行するサービスメソッドを作成します。
delete
メソッドの引数にIDを渡すことで、データの削除ができます。
レスポンスはないので、Promiseのジェネリクスにはvoid
を設定します。
import { Injectable, NotFoundException } from '@nestjs/common';
import { Items } from 'src/entities/items.entity';
import { ItemDto } from './dto/item.dto';
import { ItemsRepository } from './items.repository';
@Injectable()
export class ItemsService {
constructor (private readonly itemsRepository: ItemsRepository) {}
async findAll (): Promise<Items[]> {
return await this.itemsRepository.find();
}
async findById (id: string): Promise<Items> {
const foundItem = await this.itemsRepository.findOne(id);
if (!foundItem) {
throw new NotFoundException();
}
return foundItem;
}
async createItem (itemDto: ItemDto): Promise<Items> {
return await this.itemsRepository.createItem(itemDto);
}
async updateItem (id: string, itemDto: ItemDto): Promise<Items> {
let foudnItemToUpdate = await this.findById(id); // 更新するデータを取得
foudnItemToUpdate.name = itemDto.name; // nameを更新
foudnItemToUpdate.price = Number(itemDto.price); // priceを更新
foudnItemToUpdate.updatedAt = new Date().toISOString(); // 更新日時を更新
return await this.itemsRepository.save(foudnItemToUpdate); // データ保存
}
// 追加=============================================
async deleteItem (id: string): Promise<void> {
await this.itemsRepository.delete(id);
}
// ↑↑↑↑============================================
}
11-2. コントローラーの編集
DELETEメソッドでリクエストを受けた際に、パラメータとして渡ってきた商品IDを引数にして、作成したサービスメソッドdeleteItem
を実行します。
import { Body, Controller, Delete, Get, Param, Patch, Post } from '@nestjs/common';
import { Items } from 'src/entities/items.entity';
import { ItemsService } from './items.service';
import { ItemDto } from './dto/item.dto'
@Controller('items')
export class ItemsController {
constructor (private readonly itemsService: ItemsService) {}
@Get()
async findAll (): Promise<Items[]> {
return await this.itemsService.findAll();
}
@Get(':id')
async findById (@Param() id: string): Promise<Items> {
return await this.itemsService.findById(id);
}
@Post()
async createUser (@Body() itemDto: ItemDto): Promise<Items> {
return await this.itemsService.createItem(itemDto);
}
@Patch(':id')
async updateItem (
@Param() id: string,
@Body() itemDto: ItemDto
): Promise<Items> {
return await this.itemsService.updateItem(id, itemDto);
}
// 追加=============================================
@Delete(':id')
async deleteItem (@Param() id: string): Promise<void> {
return await this.itemsService.deleteItem(id);
}
// ↑↑↑↑============================================
}
11-3. 動作確認
削除したい既存のデータのid
をコピーします。
メソッドをDELETE
にして、URLをhttp://localhost:3000/items/{コピーしたid}
にして実行します。
エラーが出なければ、正常に削除処理が終了しています。
メソッドをGET
にして、URLをhttp://localhost:3000/items/{コピーしたid}
で1件取得APIを実行し、404NotFoundエラーが返ってくれば、削除APIの実装が完了です!👏
あとがき
これにてNestJSを使用したCRUD実装が完了です!!
認証機能の実装などの記事も今後書いてみたいと思っています。
この記事がNestJSの学習に少しでもお力になれたら幸いです!