1
/
5

NestJSでREST(その3)

前回まで

NestJSでREST(その2) | 株式会社ROBON
前回までNestJSのCLIでWebサーバー部分はできちゃいました。👏データベースと繋ぐTypeORM(とPostgres)を導入本家を含めて、mysqlが多いような気がしますが、今回は、別件で...
https://www.wantedly.com/companies/company_5181558/post_articles/897242

TypeORMとPostgresの設定ができました。👏

TypeORMを使って、モジュールを完成させる

NestJSは、DIなので依存関係はうるさくないのですが、下からやります。(実は、ORMだけじゃなくてDIも嫌いです。)

service

データベース呼び出しはTypeORMがやってくれる(はずな)ので、serviceは、TypeORM呼び出しをやります。


@@ -1,26 +1,70 @@

-import { Injectable } from '@nestjs/common';
+import {
+ Injectable,
+ NotFoundException,
+ InternalServerErrorException,
+} from '@nestjs/common';
+import { InjectRepository } from '@nestjs/typeorm';
+import { DeleteResult, Repository } from 'typeorm';
import { CreateCustomerDto } from './dto/create-customer.dto';
import { UpdateCustomerDto } from './dto/update-customer.dto';
+import { Customer } from './entities/customer.entity';

@Injectable()
export class CustomersService {
- create(createCustomerDto: CreateCustomerDto) {
- return 'This action adds a new customer';
+ constructor(
+ @InjectRepository(Customer)
+ private customersRepository: Repository<Customer>,
+ ) {}
+
+ async create(createCustomerDto: CreateCustomerDto): Promise<Customer> {
+ return await this.customersRepository.save(createCustomerDto).catch((e) => {
+ throw new InternalServerErrorException(e.message);
+ });
}

- findAll() {
- return `This action returns all customers`;
+ async findAll(): Promise<Customer[]> {
+ return await this.customersRepository.find().catch((e) => {
+ throw new InternalServerErrorException(e.message);
+ });
}

- findOne(id: number) {
- return `This action returns a #${id} customer`;
+ async findOne(id: number): Promise<Customer> {
+ const customer = await this.customersRepository.findOneBy({
+ customerId: id,
+ });
+ if (!customer) {
+ throw new NotFoundException(`Customer not found (${id})`);
+ }
+ return customer;
}

- update(id: number, updateCustomerDto: UpdateCustomerDto) {
- return `This action updates a #${id} customer`;
+ async update(
+ id: number,
+ updateCustomerDto: UpdateCustomerDto,
+ ): Promise<Customer> {
+ await this.customersRepository
+ .update({ customerId: id }, updateCustomerDto)
+ .catch((e) => {
+ throw new InternalServerErrorException(e.message);
+ });
+ const customer = await this.customersRepository.findOneBy({
+ customerId: id,
+ });
+ if (!customer) {
+ throw new NotFoundException(`Customer not found (${id})`);
+ }
+ return customer;
}

- remove(id: number) {
- return `This action removes a #${id} customer`;
+ async remove(id: number): Promise<DeleteResult> {
+ const result = await this.customersRepository
+ .delete({ customerId: id })
+ .catch((e) => {
+ throw new InternalServerErrorException(e.message);
+ });
+ if (!result.affected) {
+ throw new NotFoundException(`Customer not found (${id})`);
+ }
+ return result;
}
}

長いのですが、上から、constructorでRepositoryをインジェクションします。

そして、create 以下の全メソッドをasyncにして、戻りをPromiseにします。
これは、TypeORMのRepositoryのメソッドがPromiseを返してくれる非同期のメソッドなので、awaitで非同期関数内で同期します。(Node.jsが高速なのは非同期のおかげだと思うので、非同期が難しくても頑張ってついていきましょう)

あとは、返したいStatusCodeに対応する例外を発生させます。

controller

controllerは、serviceを呼び出しますが、serviceのメソッドが非同期になったので、controllerも非同期にします。

@@ -1,34 +1,49 @@

-import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common';
+import {
+ Controller,
+ Get,
+ Post,
+ Body,
+ Put,
+ Param,
+ Delete,
+} from '@nestjs/common';
+import { DeleteResult } from 'typeorm';
import { CustomersService } from './customers.service';
import { CreateCustomerDto } from './dto/create-customer.dto';
import { UpdateCustomerDto } from './dto/update-customer.dto';
+import { Customer } from './entities/customer.entity';

@Controller('customers')
export class CustomersController {
constructor(private readonly customersService: CustomersService) {}

@Post()
- create(@Body() createCustomerDto: CreateCustomerDto) {
- return this.customersService.create(createCustomerDto);
+ async create(
+ @Body() createCustomerDto: CreateCustomerDto,
+ ): Promise<Customer> {
+ return await this.customersService.create(createCustomerDto);
}

@Get()
- findAll() {
- return this.customersService.findAll();
+ async findAll(): Promise<Customer[]> {
+ return await this.customersService.findAll();
}

@Get(':id')
- findOne(@Param('id') id: string) {
- return this.customersService.findOne(+id);
+ async findOne(@Param('id') id: string): Promise<Customer> {
+ return await this.customersService.findOne(+id);
}

- @Patch(':id')
- update(@Param('id') id: string, @Body() updateCustomerDto: UpdateCustomerDto) {
- return this.customersService.update(+id, updateCustomerDto);
+ @Put(':id')
+ async update(
+ @Param('id') id: string,
+ @Body() updateCustomerDto: UpdateCustomerDto,
+ ): Promise<Customer> {
+ return await this.customersService.update(+id, updateCustomerDto);
}

@Delete(':id')
- remove(@Param('id') id: string) {
- return this.customersService.remove(+id);
+ async remove(@Param('id') id: string): Promise<DeleteResult> {
+ return await this.customersService.remove(+id);
}
}

あとは、オリジナルはupdateのHTTPメソッドがPatchだったのですが、Putにしちゃいました。

module

TypeORMのCustomerの機能をインポートします。

@@ -1,9 +1,12 @@

import { Module } from '@nestjs/common';
+import { TypeOrmModule } from '@nestjs/typeorm';
import { CustomersService } from './customers.service';
import { CustomersController } from './customers.controller';
+import { Customer } from './entities/customer.entity';

@Module({
+ imports: [TypeOrmModule.forFeature([Customer])],
controllers: [CustomersController],
- providers: [CustomersService]
+ providers: [CustomersService],
})
export class CustomersModule {}

次回は

途中で書いた「設定が丸見えなの」をなんとかして、最初に「やりたいこと」で書いた全体を仕上げて、全体のソースコードも公開したいと思います。

Invitation from 株式会社ROBON
If this story triggered your interest, have a chat with the team?
株式会社ROBON's job postings

Weekly ranking

Show other rankings
Like 荒木 岳夫's Story
Let 荒木 岳夫's company know you're interested in their content