0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TypeScript + Prisma + NestJSでGraphQLサーバを作ってみる

Posted at

はじめに

TypeScriptとPrismaとNextJSを使ってGraphQLサーバーの作成を行います。

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 --save-dev      //Prismaのパッケージをインストール
npm install @prisma/client
npx prisma init               //prismaの初期化

prisma/schema.prisma と .envファイルが生成されるので接続したいデータベースに合わせて設定していきます。

今回は、supabaseを使用します。

prisma/schema.prisma
generator client {
 provider = "prisma-client-js"
}

datasource db {
 provider  = "postgresql"
 url       = env("DATABASE_URL")
}
.env
DATABASE_URL="postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=SCHEMA"

3.テーブルの作成

今回はタイトルと本文と公開フラグのカラムを持った Post テーブルを作成します。

prisma/schema.prisma
model Post {
  id        Int     @default(autoincrement()) @id
  title     String
  content   String
  published Boolean @default(false)
}

以下のコマンドを実行し、マイグレーションファイルの生成とマイグレーションの実行します。

npx prisma migrate dev --name post

4. Prisma Studio でデータ追加してみる

PrismaにはPrisma Studioというデータベースに対してCRUDの操作ができるGUIが付いています。

以下のコマンドでPrisma Studioを起動して、レコードを追加してみましょう。

npx prisma studio

http://localhost:5555 にアクセスして Post テーブルにレコードを追加してみてください。

5.NestJSでPrismaクライアントを使用する

NestJSでPrismaクライアントを使用するために、src 配下に prisma.service.ts というファイルを作成し、次のコードを追加します。

、module,テストのファイルではproviderに記述しなければエラーが出る。

参考ドキュメント

src/prisma.service.ts
import { Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';

@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
  async onModuleInit() {
    await this.$connect();
  }
}

これでPrismaServiceからDB操作のためのメソッドを呼び出すことができるようになりました。

6.GraphQLのパッケージをインストール

NestJSの GraphQLのページを参考に必要なパッケージをインストールします。

npm install @nestjs/graphql @nestjs/apollo graphql apollo-server-express

7.NestJSのGraphQLプラグインの有効化

NestJSのGraphQLプラグインを有効化するとコードをシンプルにできるので、nest-cli.jsoncompilerOptions を追加して有効化しておきます。

NestJS で GraphQL サーバーを開発の開発には、コードファーストとスキーマファーストのアプローチがあります。どちらを採用しても、「Schema、データ、Resolver を用意すれば GraphQL サーバーは動かせる」という原理に変わりありません。この選択は、Schema をどうやって作成するか という違いです。

今回はコードファーストのアプローチを取ります。
コードファーストのアプローチでは、TypeScriptのクラスとデコレータを使用してクラス定義からGraphQLのSDLを生成します。
このプラグインはコードファーストのアプローチのみ適用されます。

nest-cli.json
{
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  "compilerOptions": {
    "plugins": ["@nestjs/graphql"]
  }
}

参考ドキュメント

8.テーブルの各データをモデルとして定義

今回は一覧を取得、レコード新規作成したいので以下のようなモデルを実装します。
このクラスはレスポンスのシリアライザかつschema.gql自動生成のための情報です。

現時点のPostのDBテーブルの構造に合わせてPost のObject Typeを作成してみましょう。
Post クラスを作り、@ObjectType() のデコレータを付けます。

@nestjs/graphqlモジュールから必要なデコレーターと型をインポートしています。

npm runstart:devを実行した際に、app.module.tsautoSchemaFileで設定した場所に、自動的にschema.gqlが作成されます。

src/post/models/post.model.ts
import { Field, ID, ObjectType } from '@nestjs/graphql';

@ObjectType()
export class Post {
  @Field(() => ID)
  id: number;
  title: string;
  content: string;
  published: boolean;
}

GraphQLプラグインを有効化していない場合は各プロパティに @Field() を付ける必要がありますが、有効化している場合は@Field()を勝手につけてくれます。

number はデフォルトではGraphQLの Float に変換されるため、ここでは ID になるよう明示的に @Field(() => ID) を指定しています。
参照

9.Resolverの作成

続いて、GraphQLでデータ操作を行うためのResolverを作成していきます。
今回は、Post の一覧を取得するQueryとレコードを新規作成するMutationを作成します。

Resolverを作るには、Resolverクラスを作成し、@Resolver() のデコレータを付けます。
そして、QueryとMutationの関数には @Query()@Mutation()、引数には @Args() を付けます。
これらの情報からGraphQLのスキーマが生成されます。

src/posts.post.resolver.ts
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import { Post } from './models/post.model';
import { PrismaService } from 'src/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('title') title: string,
  @Args('content') content: string,
) {
  return this.prisma.post.create({ data: { title, content} });
}
}

constructor(private prisma: PrismaService) {} でインスタンス化しています。

QueryやMutationの関数の中では、PrismaClientを使ってレコードの取得や作成を行っています。

10. AppModuleに必要なモジュールとクラスを追加

graphqlモジュールをNestJSアプリケーションに組み込み初期化します。
AppModule に GraphQLModule と先程作成した PrismaService、 PostResolver を追加します。

src/app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { PrismaService } from './prisma.service';
import { PostResolver } from './posts/posts.resolver';
import { join } from 'path';

@Module({
  imports: [
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
      autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
    }),
  ],
  controllers: [AppController],
  providers: [AppService, PrismaService, PostResolver],
})
export class AppModule {}

GraphQLModuleのforRoot()には GraphQL のオプションを設定できます。
autoSchemaFile: join(process.cwd(), 'src/schema.gql')autoSchemaFileプロパティによって、プロジェクトのsrcディレクトリに自動的にGraphQLスキーマファイルが生成されるようにしています。
モデルを定義したファイルに適当なデコレータを付与することで、自動的にgqlファイルを作成するようにできます。

この設定により、NestJSアプリケーションにGraphQLのサポートが追加されます。

Moduleの補足

@Moduleデコレータのプロパティ
・providers: @Injectableデコレータが付いたクラスを記述
・controllers @Controllerデコレータが付いたクラスを記述
・imports: モジュール内部で必要な外部モジュールを記述
・exports: 外部のモジュールにエクスポートしたいもの

参考ドキュメント

参照

参照

動作確認

npm run start

Queryで記事の一覧を取得してみます。

クエリ ``` query { posts { id title content published } } ```

記事の作成をしてみます。

クエリ ``` mutation { createPost(title: "piyo", content: "3記事目の本文です。") { id title content published } } ```

参照

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?