Prisma には DB への Seeding の機能が搭載されています。
この機能を用いて、Docker コンテナで動作する MySQL に初期データの投入作業を行ってみたので、備忘録としてブログに残します。
環境
MySQL コンテナ
Docker compose を用いて、MySQL コンテナを構築します。今回は MySQL 8.0 のイメージを使用します。
volumes: db: services: db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: example command: mysqld volumes: - type: volume source: db target: /var/lib/mysql ports: - 127.0.0.1:3306:3306
docker compose up
Prisma スキーマ
単純なスキーマを作成します。model が2つほどあれば十分でしょう。
generator client { provider = "prisma-client-js" } datasource db { provider = "mysql" url = "mysql://root:password@localhost:3306/example" // 本来ハードコーディングするべきではない⚠️ } model User { id Int @id @default(autoincrement()) name String tasks Task[] created_at DateTime @default(now()) updated_at DateTime @default(now()) } model Task { id Int @id @default(autoincrement()) user User @relation(fields: [userId], references: [id]) userId Int status TaskStatus createdAt DateTime @default(now()) updatedAt DateTime @default(now()) } enum TaskStatus { TODO IN_PROGRESS DONE }
Prisma スキーマと MySQL スキーマを同期します。
npx prisma db push
テーブルの作成を確認します。テーブル名、カラム名はスネークケースが好みですが、今回は一旦見逃しています。
% docker compose exec db sh sh-4.4# mysql -uroot -p (snip) mysql> use example; (snip) mysql> show tables; +-------------------+ | Tables_in_example | +-------------------+ | Task | | User | +-------------------+ 2 rows in set (0.00 sec)
Seed スクリプト
User と Task を1件ずつ作成するスクリプトを作成します。@prisma/client を使用するために、クライアントコードの生成コマンドも実行しておきます。
npx prisma generate
import { PrismaClient } from "@prisma/client"; const prisma = new PrismaClient({ log: ["query"], }); async function main() { await prisma.user.create({ data: { name: "Alice", tasks: { create: { status: "TODO", }, }, }, }); } main() .then(async () => { await prisma.$disconnect(); }) .catch(async (e) => { console.error(e); await prisma.$disconnect(); process.exit(1); });
package.json に prisma.seed のフィールドを追加します。
(snip) "prisma": { "seed": "ts-node prisma/seed.ts" }, (snip)
実際に試してはいませんが、Next.js のプロジェクトである場合はスクリプト実行コマンドにコンパイルオプションが必要であるようです。
ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts
Seeding 実行
コマンドを打って Seeding を実行します。
% npx prisma db seed Environment variables loaded from .env Running seed command `ts-node prisma/seed.ts` ... prisma:query BEGIN prisma:query INSERT INTO `example`.`User` (`id`,`name`,`created_at`,`updated_at`) VALUES (?,?,?,?) prisma:query INSERT INTO `example`.`Task` (`id`,`userId`,`status`,`created_at`,`updated_at`) VALUES (?,?,?,?,?) prisma:query SELECT `example`.`User`.`id`, `example`.`User`.`name`, `example`.`User`.`created_at`, `example`.`User`.`updated_at` FROM `example`.`User` WHERE `example`.`User`.`id` = ? LIMIT ? OFFSET ? prisma:query COMMIT 🌱 The seed command has been executed.
テーブルを確認します。
% docker compose exec db sh sh-4.4# mysql -uroot -p (snip) mysql> use example; (snip) mysql> select * from User; +----+-------+-------------------------+-------------------------+ | id | name | created_at | updated_at | +----+-------+-------------------------+-------------------------+ | 1 | Alice | 2024-03-09 13:19:02.744 | 2024-03-09 13:19:02.744 | +----+-------+-------------------------+-------------------------+ 1 row in set (0.00 sec) mysql> select * from Task; +----+--------+--------+-------------------------+-------------------------+ | id | userId | status | created_at | updated_at | +----+--------+--------+-------------------------+-------------------------+ | 1 | 1 | TODO | 2024-03-09 13:19:02.744 | 2024-03-09 13:19:02.744 | +----+--------+--------+-------------------------+-------------------------+ 1 row in set (0.00 sec)
まとめ
Prisma の Seeding 機能を使ってみました。
やってみて途中で気がついたのですが、npm スクリプトでも同じことできるような気がします。Prisma の機能を使うことで実現可能な便利オプションとかあるのでしょうか。
最近 Prisma に入門して SQL でテストデータ作るの面倒だなと思っていたところなので、ひとまずその課題が解消できそうなので良かったなと思います。