Chapter 05

Prismaのセットアップ

Eringi_V3
Eringi_V3
2021.09.08に更新

GraphQLの足回りが整ったので、次はDBの足回りを整えていきます。
DBはPostgresを使用します。

docker-compose.yml
version: '3.8'
services:
  postgres:
    image: postgres:10.3
    restart: always
    environment:
      - POSTGRES_USER=eringiv3
      - POSTGRES_PASSWORD=password
    volumes:
      - postgres:/var/lib/postgresql/data
    ports:
      - '5432:5432'
volumes:
  postgres:

DBを起動しておきましょう。

docker-compose up

必要な依存をインストールします。

yarn add prisma

以降は、Prismaのチュートリアルを参考に進めます。
https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgres

Prismaを初期化します。

yarn prisma init

.envにDBのURLを記載します。

DATABASE_URL="postgresql://eringiv3:password@localhost:5432

次に、Prismaのスキーマを定義します。
ここで定義した内容によって、後々使用するTypeScriptのクライアントが生成されます。
今回はTodoアプリなので、TodoモデルとUserモデルを用意します。
Todoのステータスはdone, pendingの2種類とし、enumで定義しておきます。

prisma/schema.prisma
datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

enum TodoStatus {
  done
  pending
}

model Todo {
  id          Int        @id @default(autoincrement())
  createdAt   DateTime   @default(now())
  updatedAt   DateTime   @updatedAt
  title       String     @db.VarChar(255)
  description String?
  status      TodoStatus @default(pending)
  user        User       @relation(fields: [userId], references: [id])
  userId      String
}

model User {
  id    String  @id @unique
  name  String?
  todos Todo[]
}

スキーマの定義ができたので、マイグレーションします。

prisma migrate dev --name init 

マイグレーションが完了したら、TypeScript用のPrismaクライアントを用意します。

yarn add @prisma/client

これでTypeScriptからDBを操作するための準備が整いました。
シードスクリプトを書いてPrismaクライアントを体験しましょう。
Prisma Clientではスキーマで定義したモデルごとにCRUDのAPIのメソッドが生えているのでとても直感的にクエリを書くことができます。

prisma/seed.ts
import { PrismaClient, User } from '@prisma/client';
const prisma = new PrismaClient();

const main = async () => {
  const users = await createUsers();
  const promises = users.map((user) => {
    return createTodos(user);
  });
  const todos = await Promise.all(promises);
  console.log({
    users,
    todos,
  });
};

const createUsers = async () => {
  const promises = [...Array(3)].map((_, i) => {
    const userId = `${i + 1}`;
    return prisma.user.upsert({
      where: { id: userId },
      update: {},
      create: {
        id: userId,
        name: `seed_user_${userId}`,
      },
    });
  });
  return await Promise.all(promises);
};

const createTodos = async (user: User) => {
  const promises = [...Array(3)].map((_, i) => {
    const number = i + 1;
    return prisma.todo.create({
      data: {
        title: `${user.name}_todo_${number}_title`,
        description: `${user.name}_todo_${number}_description`,
        userId: user.id,
        status: 'pending',
      },
    });
  });
  return await Promise.all(promises);
};

main()
  .catch((e) => {
    console.error(e);
    process.exit(1);
  })
  .finally(async () => {
    await prisma.$disconnect();
  });

実行します。

yarn ts-node prisma/seed.ts

DBの状態をみてみましょう。
PrismaにはブラウザからDBを見るためのツールが付属しています。

yarn prisma studio

TodoやUserのデータが作成されているのが確認できます。
これでPrismaのセットアップが完了しました。

このチャプター完了時のソースコード

https://github.com/EringiV3/apollo-server-prisma-todo-app/tree/305ca4fa5a9524d989f99f39d5e1839f7abe761a