<!-- markdown -->

[TOC]
# PrismaでGraphQL APIを自動生成しよう - チュートリアル

## 1. はじめに

このチュートリアルでは、Prismaのスキーマ定義から型安全なGraphQL APIを自動生成する方法を学びます。

### 完成イメージ
- データベースのスキーマを定義するだけで、GraphQLのAPIが自動生成される
- TypeScriptの型定義も自動生成される
- CRUD操作用のリゾルバーが自動で実装される

### 前提条件
- Node.js(v16以上)
- npmまたはyarn
- コマンドラインの基本的な操作

## 2. プロジェクトのセットアップ

まずは必要なツールとライブラリをインストールします:

    # プロジェクトの作成
    mkdir prisma-graphql-generator
    cd prisma-graphql-generator
    
    # package.jsonの初期化
    npm init -y
    
    # 必要なパッケージのインストール
    npm install @prisma/client apollo-server graphql
    npm install -D prisma typescript ts-node-dev @types/node typegraphql-prisma type-graphql reflect-metadata

TypeScriptの設定ファイルを作成:

    # TypeScript設定ファイルの生成
    npx tsc --init

`tsconfig.json`を以下のように編集:

    {
      "compilerOptions": {
        "target": "es2018",
        "module": "commonjs",
        "lib": ["es2018", "esnext.asynciterable"],
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "strictPropertyInitialization": false,
        "skipLibCheck": true,
        "esModuleInterop": true,
        "strict": true,
        "outDir": "./dist"
      }
    }

## 3. Prismaの設定

Prismaを初期化し、スキーマを定義します:

    # Prismaの初期化
    npx prisma init

`prisma/schema.prisma`を以下のように編集:

    datasource db {
      provider = "sqlite"
      url      = "file:./dev.db"
    }
    
    generator client {
      provider = "prisma-client-js"
    }
    
    // ここが重要: GraphQL型の自動生成設定
    generator typegraphql {
      provider = "typegraphql-prisma"
      output   = "../src/generated/type-graphql"
    }
    
    // データモデルの定義
    model User {
      id        Int       @id @default(autoincrement())
      email     String    @unique
      name      String
      posts     Post[]
      createdAt DateTime  @default(now())
    }
    
    model Post {
      id        Int      @id @default(autoincrement())
      title     String
      content   String
      published Boolean  @default(false)
      author    User     @relation(fields: [authorId], references: [id])
      authorId  Int
      createdAt DateTime @default(now())
    }

データベースの準備:

    # マイグレーションの実行
    npx prisma migrate dev --name init
    
    # GraphQL型の生成
    npx prisma generate

## 4. サーバーの実装

`src/index.ts`を作成:

    import 'reflect-metadata';
    import { PrismaClient } from '@prisma/client';
    import { ApolloServer } from 'apollo-server';
    import { buildSchema } from 'type-graphql';
    import { resolvers } from './generated/type-graphql';
    
    async function main() {
      const prisma = new PrismaClient();
    
      // 自動生成されたリゾルバーを使用してスキーマを構築
      const schema = await buildSchema({
        resolvers,
        validate: false,
      });
    
      // Apollo Serverの設定
      const server = new ApolloServer({
        schema,
        context: () => ({ prisma }),
      });
    
      // サーバーの起動
      const { url } = await server.listen(4000);
      console.log(`🚀 Server ready at ${url}`);
    }
    
    main().catch(console.error);

`package.json`にスクリプトを追加:

    {
      "scripts": {
        "dev": "ts-node-dev --no-notify --respawn --transpile-only src/index.ts",
        "generate": "prisma generate"
      }
    }

## 5. 自動生成されたコードの確認

`npx prisma generate`を実行すると、`src/generated/type-graphql`ディレクトリに以下のファイルが生成されます:

    src/generated/type-graphql/
    ├── enums/          # 列挙型の定義
    ├── models/         # モデルクラスの定義
    ├── resolvers/      # 自動生成されたリゾルバー
    └── index.ts        # エクスポート定義

生成されるリゾルバーの例:
- `createUser`
- `updateUser`
- `deleteUser`
- `users`(検索)
- `user`(1件取得)
- 同様のPost用リゾルバー

## 6. 動作確認

サーバーを起動:
    npm run dev

ブラウザで `http://localhost:4000` にアクセスし、以下のクエリを試してみましょう:

### ユーザーの作成:
    mutation {
      createUser(data: {
        email: "test@example.com"
        name: "Test User"
      }) {
        id
        email
        name
      }
    }

### 投稿の作成:
    mutation {
      createPost(data: {
        title: "First Post"
        content: "Hello, World!"
        published: true
        author: {
          connect: { id: 1 }
        }
      }) {
        id
        title
        author {
          name
        }
      }
    }

### データの取得:
    query {
      users {
        id
        name
        posts {
          title
          content
          published
        }
      }
    }

## 7. 生成されたコードのカスタマイズ

自動生成されたコードに独自の機能を追加することもできます:

    // src/resolvers/CustomUserResolver.ts
    import { Resolver, Query, Ctx } from 'type-graphql';
    import { User } from '../generated/type-graphql';
    
    @Resolver(User)
    export class CustomUserResolver {
      @Query(returns => [User])
      async activeUsers(@Ctx() ctx: any) {
        return ctx.prisma.user.findMany({
          where: {
            posts: {
              some: {
                published: true
              }
            }
          }
        });
      }
    }

## 8. まとめ

- PrismaのスキーマからGraphQL APIを自動生成できた
- CRUDオペレーションが自動実装された
- 型安全性が確保された
- カスタムリゾルバーの追加も可能

## 次のステップ
- 認証/認可の実装
- バリデーションの追加
- テストの作成
- 本番環境へのデプロイ

## トラブルシューティング

よくある問題:
1. 型が生成されない

      → `npx prisma generate`を実行

2. デコレータエラー

      → `tsconfig.json`の設定を確認

3. 実行時エラー

      → `reflect-metadata`のインポートを確認

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   最終更新のRSS