🧏

NestJS, Prisma, PostgreSQL(Docker)で...Part2

2024/08/20に公開

ユーザー登録のAPIつくっていくよ

前回の続きです
前回はDBの接続までできたことだしCreateAPI一個作ってみましょう!

とはいえNestわからんのやが😠

というバックエンド入門中の方のために若干説明しておきます

まずメインの3つ(service, controller, module)を簡単に

  • serviceは主にDBの操作を担う部分です、ロジックを書いてDBのこのテーブルにレコードを追加する、とか探してくる、とかする部分です
  • controllerはこのエンドポイント(URLのパス)にリクエストが来たらこのserviceを呼びます、といったルーティングの役割を果たします
  • moduleservice, controller, その他...をまとめて管理します。

公式
service: https://docs.nestjs.com/providers
controller: https://docs.nestjs.com/controllers
module: https://docs.nestjs.com/modules

開発の基本的な手順は

  1. schemaにDBの定義をする
  2. $ npx prisma generateして型の生成をする
  3. module, service, controllerを生成する
  4. serviceにdb操作の内容を定義する
  5. controlleに作成したどんなリクエストが来たらどのserviceを実行するか定義する
  6. moduleでつなぐ(注入する)(コマンドで生成したら大体自動で注入してくれてる)

んじゃそろそろ本題に移りましょう!

事前準備(1)

  • service内でPrismaを使うためのPrismaService定義しておく
  • 生成
    $ nest g module prisma
    $ nest g service prisma
  • 定義
# prisma.service.ts
import { Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';

@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
  async onModuleInit() {
    await this.$connect();
  }
}

事前準備(2)

  • 生成
$ nest g module user &&
nest g service user &&
nest g controller user
  • request bodyの型定義しておくよ
# user/dto/create-user.dto.ts
export class CreateUserDto {
  username: string;
  email: string;
  password: string;
}
  • UserModuleに先ほど作成したPrismaModuleimport!(注入っていうらしい
# user.module.ts
@Module({
  imports: [PrismaModule],
  providers: [UserService],
  controllers: [UserController],
})

Service作成

  • $ npm i bcrypt(平文字をhash化してくれるやつ)
# user.service.ts
import { Injectable } from '@nestjs/common';
import { User } from '@prisma/client';
import * as bcrypt from 'bcrypt';

import { PrismaService } from '../prisma/prisma.service';
import { CreateUserDto } from './dto/create-user.dto';

@Injectable()
export class UserService {
  constructor(private prisma: PrismaService) {}

  async create(data: CreateUserDto): Promise<User> {
    const hashedPassword = await bcrypt.hash(data.password, 10);
    return this.prisma.user.create({
      data: {
        ...data,
        password: hashedPassword,
      },
    });
  }
}

受け取ったdataの内、passwordをhash化してからdataに入れ直してcreateします

Controller作成

# user.controller.ts
import { Body, Controller, Post } from '@nestjs/common';

import { UserService } from './user.service';
import { CreateUserDto } from './dto/create-user.dto';
import { User } from '@prisma/client';

@Controller('user')
export class UserController {
  constructor(private readonly userService: UserService) {}

  @Post('register')
  async register(@Body() createUserDto: CreateUserDto): Promise<User> {
    return this.userService.create(createUserDto);
  }
}

POST user/registerてリクエストが来たらBodyの内容をそのままuserService.createに渡して呼び出すてだけです

※ ここまででUser型ないよってエラーでてる方、

$ npx prisma generateするとnode_modules/@prisma/clientに型が自動生成されます

動作確認

docker, Nestの起動

$ docker-compose up -d
$ npm run start:dev

私はpostmanを使います、がcurlでもvsCodeの拡張機能でもなんでもいいです
(installしたい方はこちらから

それでは確認してみましょう、以下の通りにPOSTしてみてください

method: POST
URL: http://localhost:3000/user/register
Body: {
  "username": "user1",
  "email": "user1@example.com",
  "password": "password"
}

えいっ!
..
問題なさそうですね。。。?

prisma studioからも、1件リクエスト通りに追加されてることを確認できました!🎉

乙!

Next ▶ 認証を必要とするエンドポイント(JWT)ってやつを作っていこうと思います

Discussion