🦁
NestJSでREST(その3)
前回まで
TypeORMとPostgresの設定ができました。👏
TypeORMを使って、モジュールを完成させる
NestJSは、DIなので依存関係はうるさくないのですが、下からやります。(実は、ORMだけじゃなくてDIも嫌いです。)
service
データベース呼び出しはTypeORMがやってくれる(はずな)ので、serviceは、TypeORM呼び出しをやります。
src/customers/customers.service.ts
@@ -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も非同期にします。
src/customers/customers.controller.ts
@@ -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の機能をインポートします。
src/customers/customers.module.ts
@@ -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 {}
次回は
途中で書いた「設定が丸見えなの」をなんとかして、最初に「やりたいこと」で書いた全体を仕上げて、全体のソースコードも公開したいと思います。
GitHubで編集を提案
Discussion