NestJS × Prisma × PostgreSQLでプロジェクトを動かすまでの環境構築の流れ

最初に

今回は、NestJsの話題です。疲れてしまったので前回のようなハイテンションではないですがどうぞよろしくお願いします。

実際のコード

実行可能なコードをGithubで公開しています。もし気になる場合は

$ git clone git@github.com:mtugb/hogeNestjsTutorial.git

を行って自分の環境でも試すことが可能です。

使用環境

OSWindows11(WSL不使用)
PostgreSQLv18.1。インストーラを公式サイトからダウンロードして、windowsに直接インストールしたもの
NodeJs, Npmv24.9.0, v11.6.0。 導入方法は同上

[注意] postgreSql, nodeJs, npmはインストール済みを想定。

[補足] pnpmではなくnpmの人はpnpmをnpmに置き換えて実行すれば同じように動きます。


NestJS プロジェクトの作成

まずは Nest CLI をグローバルインストールし、新規プロジェクトを作成します。

$ npm i -g @nestjs/cli
$ nest new hoge

Prisma の導入

Prisma を開発依存として追加し、Prisma Client もインストールします。

prisma generateなどは本番環境では実行する必要がないため、-Dオプション(–save-devと同じ)を指定します。

$ pnpm add prisma -D
$ pnpm add @prisma/client

Prisma の初期化。

$ pnpx prisma init

これで prisma/ ディレクトリと schema.prisma が生成されます。


PostgreSQL の準備

今回は psql コマンドを使わず(パスを通していなかったため)、PostgreSQL のシェルアプリをダブルクリックで起動して SQL を実行しました。

CREATE ROLE hoge_admin WITH LOGIN PASSWORD 'pass';
CREATE DATABASE hoge_db OWNER hoge_admin;
ALTER ROLE hoge_admin CREATEDB;

Prisma はマイグレーション時に shadow database を作成するため、CREATEDB 権限が必要になります。


.env の設定

Prisma が接続する DB URL を .env に記述します。

DATABASE_URL="postgresql://hoge_admin:pass@localhost:5432/hoge_db"

Prisma スキーマの編集

schema.prisma に テーブル「Hoge」のモデルを追加します。

model Hoge {
  id        Int      @id @default(autoincrement())
  title     String
}

また、generator の provider を以下のように修正します。

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

⚠️ 最新版 Prisma (v6+) での注意点と解決策

ここまでの手順で DB の準備は整いましたが、実際に NestJS から接続しようとすると、いくつか「最新版特有の壁」にぶつかることがあります。私が実際に躓いたポイントと解決策をまとめました。

1. Driver Adapter の導入が必要

Prisma v6 以降、PostgreSQL などの接続には「ドライバーアダプター」の利用が推奨・必須化されています。これがないと、実行時に PrismaClientInitializationError が発生します。

参考ページ(公式)

Documentation | NestJS - A progressive Node.js framework
Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, i...

以下のパッケージを追加でインストールしてください。

$pnpm add pg @prisma/adapter-pg$ pnpm add -D @types/pg

2. NestJS 起動時に環境変数が undefined になる問題

Prisma CLI(npx prisma)は自動で .env を読み込みますが、NestJS 本体はデフォルトでは .env を読み込みません。

そのため、PrismaService のコンストラクタが動く瞬間に process.env.DATABASE_URLundefined になり、結果として SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string というエラーが発生します。

解決策:ConfigModule の導入

NestJS の標準機能である ConfigModule を使い、起動時に環境変数を確実にロードさせます。

① AppModule の修正
src/app.module.tsConfigModule をグローバルに有効化します。

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true }), // この行を追加
    // ...他のモジュール
  ],
})
export class AppModule {}

② PrismaService の修正
公式ドキュメント(Recipes: Prisma)の最新仕様に基づき、アダプターを super() に渡す形に書き換えます。

import { Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
import { PrismaPg } from '@prisma/adapter-pg';
import { Pool } from 'pg';

@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
  constructor() {
    // ConfigModuleのおかげで、ここで process.env が取得可能になる(取得方法の変更は不要)
    const url = process.env.DATABASE_URL!;
    if (!url) {
        throw new Error('DATABASE_URL is not defined in .env');
    }
    console.info(`This is Connection "${url}"`);
    const pool = new PrismaPg({ connectionString: url });
    super({ adapter: pool });
  }
}

参考ページ(公式)

Documentation | NestJS - A progressive Node.js framework
Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, i...

💡 なぜ公式ドキュメント通りで動かないのか?

公式のサンプルコードは、環境変数がシステム側から既に注入されている(Docker環境など)ことを前提に書かれていることが多いため。

ローカル開発環境では、「NestJSが立ち上がるタイミング」と「.envを読み込むタイミング」のズレを意識する必要がある、という点が今回の大きな学びでした。

Prisma Client の生成

Prisma Client を生成します。

$ pnpx prisma generate

これにより、TypeScript から DB を操作するためのPrismaクライアントが生成されます。


マイグレーションの実行

最後にマイグレーションを実行して、DB にテーブルを作成します。

$ pnpx prisma migrate dev --name init

これで Prisma と PostgreSQL の連携が完了しました。

実行

いよいよ実行の時が来ました!

$ pnpm run start:dev

これでエラー無く起動したら、

ブラウザで localhost:3000/hoge/list にアクセスしてみてください。

entriesと出ていれば成功です。

つぎに、

localhost:3000/hoge/create?title=hello

にアクセスし、

successful:trueであれば

localhost:3000/hoge/list に再びアクセスしてみて、登録されていれば、DBの追加も成功です!


まとめ

今回の手順で、NestJS × Prisma × PostgreSQL の基本的な開発環境が整いました。

いくつかつまずくポイントを振り返ると

  • Adapterを渡す処理をしていない
  • 環境変数が読み込まれない

ブログは以上です。

ブログにした経緯

自分は躓いたので、今回はこのブログを作成しました(内容をまとめる際にAIの助けを借りました)。間違っているところなどあればコメントお願いします。

コメント

タイトルとURLをコピーしました