🧔‍♀️

Next.js+PrismaのPrismaのSeed実行時に他のファイルを読み込まなかった。

に公開

Next.jsでPrismaのSeedしようとした時に外部のファイルを読み取ってくれなくて困った事案があったので、どう解決したかだけ残します。これはコンパイラーのmoduleが違うことによってImportの書き方、やり方が違うことが原因のようですが、あまり正しく理解できてない気がするので解決法だけ共有とします。

結論として、tsconfig.jsonの"compilerOptions"の"module"を、デフォルトの"esnext"から"CommonJS"などに変更するとprisma/以下のディレクトリでも他のファイルの値が読めます。ただし、プロジェクト全体でコンパイラのモジュールを"commonJS"に変えてしまう弊害もあるかもなので、npx prisma db seedのコマンドを実行するときだけ参照しに行くtsconfig.local.jsonを作成して、そいつはmoduleを"commonJS"にしておきます。

状況

テスト用のデータであるcategoriesをINSERTするときに、シーディングを実行するmain.tsに全て書くと見通しが悪かったので、categories.tsにデータの中身だけ分けてmain.tsでImportするようにしましたが、main.tsからcategories.tsの中身が読み取れなかったためにnpx prisma db seedしてもError: Cannot find module [categories.tsのパス]が出て作業が進まない、という状況でした。

// prisam/seeder/main.ts(Seedingするためのデータがあるファイル)

import { categories } from "./categories";

// 実行するMainメソッド
async function main() {
  // categories
  for (const category of categories) {
    await prisma.majorCategory.create({
      data: category,
    });
  }
}
// prisma/seeder/categories.ts
// categories.tsのコード。定数でオブジェクトの配列を置いているだけ。

export const categories = [
    ..... ,
];

解決

参考にある記事にしたがってtsconfig.local.jsonを作成し以下のように設定。

// tsconfig.local.json
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "CommonJS" // esnextだとImportが使えないので、seedだけCommonJSにする
  }
}

次にpackage.jsonでPrismaのSeedコマンドをカスタマイズ。

{
    ..., // その他のプロパティ
  "prisma": {
    "seed": "ts-node --project tsconfig.local.json prisma/seeder/main.ts"
  },
    ... // その他のプロパティ
}

Seederの中身は全く変えずにnpx prisma db seedを実行。

// コンソールのログ
npx prisma db seed
Environment variables loaded from .env
Running seed command `ts-node --project tsconfig.local.json prisma/seeder/seed.ts` ...

🌱  The seed command has been executed.

これでひとまずSeedは通りました。

参考

https://zenn.dev/hayata_yamamoto/scraps/a5d1135a299531

ESMの話
https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Modules

Discussion