このチュートリアルでは、Prismaのスキーマ定義から型安全なGraphQL APIを自動生成する方法を学びます。
まずは必要なツールとライブラリをインストールします:
# プロジェクトの作成
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"
}
}
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
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"
}
}
npx prisma generateを実行すると、src/generated/type-graphqlディレクトリに以下のファイルが生成されます:
src/generated/type-graphql/
├── enums/ # 列挙型の定義
├── models/ # モデルクラスの定義
├── resolvers/ # 自動生成されたリゾルバー
└── index.ts # エクスポート定義
生成されるリゾルバーの例:
createUserupdateUserdeleteUserusers(検索)user(1件取得)サーバーを起動: 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
}
}
}
自動生成されたコードに独自の機能を追加することもできます:
// 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
}
}
}
});
}
}
よくある問題:
型が生成されない
→ npx prisma generateを実行
デコレータエラー
→ tsconfig.jsonの設定を確認
実行時エラー
→ reflect-metadataのインポートを確認