プロジェクトの作成
NestJS CLI の導入
先ず、NestJS CLI をインストールします。
npm i -g @nestjs/cli
nest new の実行
次に、nest new コマンドを使い、プロジェクトを作成します。
今回は、tutorial-app というプロジェクト名を指定しています。
nest new tutorial-app
実行すると、使用するパッケージマネージャーを聞かれます。
今回は、npm を選択します。
CRUD の実装
nest g コマンド の実行
nest g コマンドを実行し、BooksModule、BooksController、BooksService を作成します。
nest g module books
nest g controller books --no-spec
nest g service books --no-spec
Controller とService は、オプションをつけずに実行すると、 books.controller.spec.ts のようなテストファイルが自動で作成されます。
今回はテストは行わないので、--no-spec オプションをつけて、テストファイルなしで、Controller とService を作成します。
依存性の注入
BooksService で定義したメソッドをBooksController で呼び出せるように、依存性の注入を行います。
import { Controller, Get } from '@nestjs/common';
import { BooksService } from './books.service';
@Controller('books')
export class BooksController {
constructor(private readonly booksService: BooksService) {} // booksService をインスタンス化する
}
Book Model の作成
Book の型を定義したModel を定義します。
import { BookStatus } from './book-status.enum';
export interface Book {
id: string;
name: string;
status: BookStatus;
}
本の貸し出し状況をstatus で管理するため、enum として、別ファイルに切り出す。
export enum BookStatus {
RENTABLE = 'RENTABLE',
LENT_OUT = 'LENT_OUT',
}
TypeORM の導入時にModel とTable の紐付けを定義するBookEntity というものを作成します。
その時にBook Model は不要になるので、全てBookEntity に置き換えることになります。
Create 機能の実装
先ず、 値を保存するためのcreate メソッドをBooksServiceに用意します。
import { Injectable } from '@nestjs/common';
import { Book } from './book.model';
@Injectable()
export class BooksService {
private books: Book[] = [];
create(book: Book) {
this.books.push(book);
return book;
}
}
保存する値は、Post リクエストのBody からBooksController を介してBooksService に渡します。
BooksController にPost リクエストに対して、BooksService のcreate メソッドを呼び出す処理を書いていきます。
import { Body, Controller, Get, Post } from '@nestjs/common';
import { BookStatus } from './book-status.enum';
import { Book } from './book.model';
import { BooksService } from './books.service';
@Controller('books')
export class BooksController {
constructor(private readonly booksService: BooksService) {}
@Post()
create(@Body('id') id: string, @Body('name') name: string): Book {
const book: Book = {
id,
name,
status: BookStatus.RENTABLE,
};
return this.booksService.create(book);
}
}
動作確認として、Postman を使います
http://localhost:3000/books にBody に保存するプロパティの値を渡し、POST でリクエストを送ります。
保存が成功していいるとリクエストに対してbook 変数の値が返ってきます。
Read 機能の実装
保存したBook の値を確認するため、BooksService にBook の内容を取得するためのロジックを記述します。
全件取得機能
保存したBook の値を全て取得するfindAll メソッドをBooksService に記述していきます。
import { Injectable } from '@nestjs/common';
import { Book } from './book.model';
@Injectable()
export class BooksService {
private books: Book[] = [];
findAll() {
return this.books;
}
create(book: Book) {
this.books.push(book);
return book;
}
}
BooksController にGet リクエストに対し、BooksService のfindAll メソッドを呼び出す処理を追記します。
import { Body, Controller, Get, Post } from '@nestjs/common';
import { BookStatus } from './book-status.enum';
import { Book } from './book.model';
import { BooksService } from './books.service';
@Controller('books')
export class BooksController {
constructor(private readonly booksService: BooksService) {}
@Get()
findAll() {
return this.booksService.findAll();
}
@Post()
create(@Body('id') id: string, @Body('name') name: string): Book {
const book: Book = {
id,
name,
status: BookStatus.RENTABLE,
};
return this.booksService.create(book);
}
}
http://localhost:3000/books にGET でリクエストを送り、Books の配列の値が返ってくれば成功です。
配列には、Post で保存したBook の値が入っています。
ID を指定した取得
全件取得機能が作れたら、次に指定したID を持ったBook を取り出すfindById メソッドをBooksService に記述します。
import { Injectable } from '@nestjs/common';
import { Book } from './book.model';
@Injectable()
export class BooksService {
private books: Book[] = [];
findAll() {
return this.books;
}
findById(id: string): Book {
return this.books.find((book) => book.id === id);
}
create(book: Book) {
this.books.push(book);
return book;
}
}
取得したいID は、books/1 のようにURL に記述して渡します。
BooksController にGet リクエストに対し、BooksService のfindById メソッドを呼び出す処理を追記します。
import { Body, Controller, Get, Post } from '@nestjs/common';
import { BookStatus } from './book-status.enum';
import { Book } from './book.model';
import { BooksService } from './books.service';
@Controller('books')
export class BooksController {
constructor(private readonly booksService: BooksService) {}
@Get()
findAll() {
return this.booksService.findAll();
}
@Get(':id')
findById(@Param('id') id: string): Book {
return this.booksService.findById(id);
}
@Post()
create(@Body('id') id: string, @Body('name') name: string): Book {
const book: Book = {
id,
name,
status: BookStatus.RENTABLE,
};
return this.booksService.create(book);
}
}
http://localhost:3000/books/:id にGET でリクエストを送り、指定したid のBook の値が返ってくれば成功です。
Update 機能の実装
指定したID を持ったBook のstatus を更新するupdateStatus メソッドをBooksService に記述します。
リクエストで渡したID と一致するBook はfindById を使って取得します。
import { Injectable } from '@nestjs/common';
import { Book } from './book.model';
@Injectable()
export class BooksService {
private books: Book[] = [];
findAll() {
return this.books;
}
findById(id: string): Book {
return this.books.find((book) => book.id === id);
}
create(book: Book) {
this.books.push(book);
return book;
}
updateStatus(id: string): Book {
const book = this.findById(id);
book.status = BookStatus.LENT_OUT;
return book;
}
}
BooksController にPATCH リクエストに対し、BooksService のfindById メソッドを呼び出す処理を追記します。
import { Body, Controller, Get, Post } from '@nestjs/common';
import { BookStatus } from './book-status.enum';
import { Book } from './book.model';
import { BooksService } from './books.service';
@Controller('books')
export class BooksController {
constructor(private readonly booksService: BooksService) {}
@Get()
findAll() {
return this.booksService.findAll();
}
@Get(':id')
findById(@Param('id') id: string): Book {
return this.booksService.findById(id);
}
@Post()
create(@Body('id') id: string, @Body('name') name: string): Book {
const book: Book = {
id,
name,
status: BookStatus.RENTABLE,
};
return this.booksService.create(book);
}
@Patch(':id')
updateStatus(@Param('id') id: string): Item {
return this.itemsService.updateStatus(id);
}
}
http://localhost:3000/books/:id にPATCH でリクエストを送り、指定したid のBook status の値がRENTABLE からLENT_OUT に更新されていれば成功です。
Delete 機能の実装
BooksService に リクエストで指定したid の値と一致した、id を持つBook を削除するdelete メソッドを用意します。
import { Injectable } from '@nestjs/common';
import { Book } from './book.model';
import { BookStatus } from './book-status.enum';
@Injectable()
export class BooksService {
private books: Book[] = [];
findAll() {
return this.books;
}
findById(id: string): Book {
return this.books.find((book) => book.id === id);
}
create(book: Book) {
this.books.push(book);
return book;
}
updateStatus(id: string): Book {
const book = this.findById(id);
book.status = BookStatus.LENT_OUT;
return book;
}
delete(id: string): void {
this.books = this.books.filter((book) => book.id !== id);
}
}
BooksController にDELETE リクエストに対し、BooksService のdelete メソッドを呼び出す処理を追記します。
import { Body, Controller, Delete, Get, Param, Post } from '@nestjs/common';
import { BookStatus } from './book-status.enum';
import { Book } from './book.model';
import { BooksService } from './books.service';
@Controller('books')
export class BooksController {
constructor(private readonly booksService: BooksService) {}
@Get()
findAll() {
return this.booksService.findAll();
}
@Post()
create(@Body('id') id: string, @Body('name') name: string): Book {
const book: Book = {
id,
name,
status: BookStatus.RENTABLE,
};
return this.booksService.create(book);
}
@Delete()
delete(@Param('id') id: string): void {
this.booksService.delete(id);
}
}
http://localhost:3000/books/:id にDELETE でリクエストを送った後、http://localhost:3000/books にGET でリクエストを送ります。
指定したid のBook が削除されていれば成功です。