TypeScript + PrismaでGraphQLサーバを作ってみる
TypeScript + PrismaでGraphQLサーバを作ってみよっと。
初期設定が面倒なので今回はNestJSを使うことにする。
このページが参考になりそう。
NestJSのサイトを参考にNestJSとPrismaのセットアップをする。
1. NestJSプロジェクトの作成
$ npm install -g @nestjs/cli
$ nest new my-app
試しにサーバを起動してみる。
$ cd my-app
$ npm run start
http://localhost:3000/ にアクセスすると Hello World!
が表示される。
2. Prismaのセットアップ
$ npm install @prisma/client
$ npm install prisma --save-dev
$ npx prisma init
3. データベース接続
prisma/schema.prisma
と .env
を自分の環境に合わせて編集する。
今回はMySQLを使う。
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
DATABASE_URL="mysql://USER:PASSWORD@HOST:PORT/DATABASE"
※大文字の部分を自分の環境の値に置き換える
4. テーブルの作成
今回は記事メディアのようなサービスを想定。
Post
モデルの定義を schema.prisma
ファイルに追加する。
model Post {
id Int @default(autoincrement()) @id
title String
content String
published Boolean @default(false)
}
以下のコマンドでマイグレーションファイルを生成する。
post
の部分はディレクトリ名になるのでわかりやすい名前を付ければOK。
$ npx prisma migrate dev --name post
$ tree prisma
prisma
├── migrations
│ ├── 20211117140927_post
│ │ └── migration.sql
│ └── migration_lock.toml
└── schema.prisma
マイグレーションも自動で実行される。
生成されたマイグレーションファイルの中身
-- CreateTable
CREATE TABLE `Post` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`title` VARCHAR(191) NOT NULL,
`content` VARCHAR(191) NOT NULL,
`published` BOOLEAN NOT NULL DEFAULT false,
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Prisma Studioでレコードを追加してみる。
$ npx prisma studio
http://localhost:5555 にアクセスして、GUIからレコードを追加できることを確認。
5. NestJSでPrismaクライアントを使用する
src
ディレクトリ内に prisma.service.ts
という新しいファイルを作成し、次のコードを追加する。
import { INestApplication, Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
async onModuleInit() {
await this.$connect();
}
async enableShutdownHooks(app: INestApplication) {
this.$on('beforeExit', async () => {
await app.close();
});
}
}
6. GraphQL関連のパッケージをインストール
以下のページを参考に必要なパッケージをインストール。
$ npm install @nestjs/graphql graphql graphql-tools apollo-server-express
7. NestJSのGraphQLプラグインを有効化
NestJSのGraphQLプラグインを有効化することで必要な定型コードの量を減らすことができる。
{
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"plugins": ["@nestjs/graphql"]
}
}
詳しくは以下のページ参照。
8. ObjectTypeとResolverの作成
Post
の ObjectType
を作成。
import { Field, ID, ObjectType } from '@nestjs/graphql';
@ObjectType()
export class Post {
@Field(() => ID)
id: number;
title: string;
content: string;
published: boolean;
}
Post
の Query
と Mutation
を作成。
import { Resolver, Query, Mutation, Args } from '@nestjs/graphql';
import { Post } from 'src/models/post.model';
import { PrismaService } from '../prisma.service';
@Resolver(() => Post)
export class PostResolver {
constructor(private prisma: PrismaService) {}
@Query(() => [Post])
async posts() {
return this.prisma.post.findMany();
}
@Mutation(() => Post)
async createPost(
@Args({ name: 'title', type: () => String }) title: string,
@Args({ name: 'content', type: () => String }) content: string,
) {
return this.prisma.post.create({ data: { title, content } });
}
}
9. AppModuleに必要なクラスやモジュールをインポート
AppModule
の imports
に GraphQLModule
、providers
に PrismaService
と PostResolver
を追加する。
@Module({
imports: [
GraphQLModule.forRoot({
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
}),
],
controllers: [AppController],
providers: [AppService, PrismaService, PostResolver],
})
export class AppModule {}
動作確認
以下のコマンドでサーバを起動。
$ npm run start
以下のエラーが出てサーバを起動できず。。
Error: You must `await server.start()` before calling `server.applyMiddleware()`
ググると以下の記事が見つかった。
apollo-server-express
を3系から2系にダウングレードすると、無事サーバが起動。
http://localhost:3000/graphql にアクセスするとGraphQL Playgroundが表示されました 🎉
Queryで記事を取得。
query {
posts {
id
title
content
published
}
}
Mutationで記事を作成。
mutation {
createPost(title: "piyo", content: "3記事目の本文です。") {
id
title
content
published
}
}
TypeScript + PrismaでGraphQLサーバを作ることができました 🥳
以下の記事にまとめたのでこちらはクローズ。