🌊

PrismaでLaravel風のシーダーを作る

2023/01/22に公開

シーダーは、アプリケーションを動かすのに必要なデータを登録するもののことです。Prismaでは、以下のようにシーダーがサポートされています。

  • prisma db seedで、package.jsonに登録したシードスクリプトを実行できる
  • prisma migrate resetでデータベースをリセットしたとき、リセット完了後にシードスクリプトを実行してくれる

また、Laravelでは、シーダーを実行するときに特定のシーダーのみを実行する機能があります。これは、開発中に新たに追加したテーブルにデータを登録するときなどに役立ちます。

Prisma CLIにはこの機能がなかったため、これをサポートしたスクリプトを書いてみました。

使い方

# 全てのシーダーを実行する
prisma db seed

# 特定のシーダーを実行する
npm run db:seed postSeeder

作り方

Prismaのシードスクリプトは、package.jsonprisma.seedに登録します。また、個別のシーダーを実行するためのnpm scriptを書きます。npm scriptを書いたのは、prisma db seedに追加の引数を渡すことができなかったからです。

package.json
{
  "scripts": {
    "db:seed": "ts-node --transpileOnly src/database/seeder/index.ts"
  },
  "prisma": {
    "seed": "ts-node --transpileOnly src/database/seeder/index.ts"
  }
}

シードスクリプトは以下です。引数を指定しなかった場合は全てのシーダーを実行し、シーダー名を指定すると特定のシーダーを実行します。

src/database/seeder/index.ts
import { PrismaClient } from '@prisma/client'
import { userSeeder } from './user-seeder'
import { postSeeder } from './post-seeder'
import { prisma } from "../prisma"

const databaseSeeder = {
  userSeeder,
  postSeeder,
}

type SeederName = keyof typeof databaseSeeder

async function main() {
  const seederName = process.argv[2]
  if (seederName === undefined) {
    for (const [name, seeder] of Object.entries(databaseSeeder)) {
      console.log(`Seeding: ${name}`)
      await seeder()
    }
    return
  }

  if (seederName in databaseSeeder) {
    const seeder = databaseSeeder[seederName as SeederName]
    console.log(`Seeding: ${seederName}`)
    await seeder()
    return
  }

  console.error('Error: シーダー名が正しくありません')
  process.exit(1)
}

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

個別のシーダーは単なる非同期関数です。

src/database/seeder/user-seeder.ts
import { prisma } from "../prisma"

async function userSeeder() {
  // データを登録する処理
}

参考

GitHubで編集を提案

Discussion