2019年2月12日

データベースとGraphQL Nexusの使用

GraphQL Nexusは、JavaScript/TypeScript向けのコードファーストでタイプセーフなGraphQLスキーマ構築ライブラリです。Prismaクライアントと新しいnexus-prismaプラグインを使用してデータベースに接続する方法を学びましょう。

Using GraphQL Nexus with a Database

⚠️ この記事は古く、現在非推奨となっているPrisma 1に関するものです。Prismaの最新バージョンについては、ドキュメントをお読みください。 ⚠️

要約:GraphQL Nexusによるコードファースト開発

前回の記事では、TypeScriptとJavaScript向けのコードファースト開発を可能にするGraphQLライブラリであるGraphQL Nexusを紹介しました。Nexusでは、GraphQLスキーマはプログラム的に定義および実装されます。そのため、sangria-graphql(Scala)、graphlq-ruby、またはgraphene(Python)など、他の言語のGraphQLサーバーの実証済みの手法に従っています。

今日の記事では、Prismaクライアントと新しいnexus-prismaプラグインを使用して、NexusベースのGraphQLサーバーをデータベースに接続する方法について説明します。後ほど、ブログアプリ用のGraphQL APIをゼロから構築する実践的な例を詳しく説明します。

nexus-prismaは、PostgreSQL、MySQL、MongoDBで動作します。ドキュメントはこちらをご覧ください。


TLDR:nexus-prismaプラグインの利点

  • GraphQLでのPrismaモデルのCRUD操作
  • Prismaモデルのカスタマイズ(特定のフィールドの非表示や計算フィールドの追加など)
  • 完全なタイプ安全性:GraphQLスキーマとデータベースの一貫した型セット
  • GraphQLエコシステムとの互換性(例:apollo-servergraphql-yogaなど)

nexus-prismaのワークフローの理解

ORMの代替としてのPrismaクライアント

Prismaをまだ使用したことがない場合は、その仕組みの簡単な概要を説明します。

  1. データモデルを定義するか、Prismaに既存のデータベースをイントロスペクトさせます。
  2. Prismaクライアント(つまり、タイプセーフなデータベースクライアント)を生成します。
  3. Prismaクライアントを使用して、アプリケーション(例:GraphQL API)でデータベースにアクセスします。

nexus-prismaプラグインの内部

nexus-prismaを組み合わせる場合、もう1つのステップがあります。それは、nexus-prisma-generate codegen CLIを呼び出すことです。これにより、Prismaモデル用の本格的なGraphQL CRUD APIの構成要素が生成されます。たとえば、Userモデルの場合、次のようなものが含まれます。

  • クエリ
    • user(...): User!:単一のレコードを取得します。
    • users(...): [User!]!:レコードのリストを取得します。
    • usersConnection(...): UserConnection!Relayコネクションと集計
  • ミューテーション
    • createUser(...): User!:新しいレコードを作成します。
    • updateUser(...): User:レコードを更新します。
    • deleteUser(...): User:レコードを削除します。
    • updatesManyUsers(...): BatchPayload!:複数のレコードを一括で更新します。
    • deleteManyUsers(...): BatchPayload!:複数のレコードを一括で削除します。
  • GraphQL入力型
    • UserCreateInput:レコードのすべてのフィールドをラップします。
    • UserUpdateInput:レコードのすべてのフィールドをラップします。
    • UserWhereInput:レコードのすべてのフィールドのフィルターを提供します。
    • UserWhereUniqueInput:レコードの一意のフィールドのフィルターを提供します。
    • UserUpdateManyMutationInput:一括で更新できるフィールドをラップします。
    • UserOrderByInput:フィールドによる昇順または降順の順序を指定します。

UserCreateInputUserUpdateInputは、リレーションフィールドの扱い方が異なります。

nexusnexus-prismaを使用してGraphQLサーバーコードを作成する場合、これらの操作を基に、独自のAPIニーズに合わせて公開およびカスタマイズします。

Writing GraphQL server code with nexus and nexus-prisma

CRUD構成要素を生成したら、nexus-prismaprismaObjectTypeを使用して、それらを公開(およびカスタマイズ)を開始できます。次のコードスニペットは、Prismaとnexus-prismaに基づいてTODOリストアプリ用のGraphQL APIを提供する実装を示しています。

prismaObjectTypeQueryMutationに適用しています。Queryの場合、すべてのフィールド(つまり、todotodoestodoesConnection)を保持しています。Mutationの場合、prismaFieldsを使用して、公開される操作をカスタマイズしています。

prismaFieldsを使用すると、公開する操作を選択できます。この場合、モデルを作成する操作(createTodo)のみを保持します。生成されたCRUD構成要素から、updateTododeleteTodoも含めず、特定のTodoをチェックオフする独自のmarkAsDone(id: ID!)ミューテーションを実装します。


例:標準CRUDからカスタマイズされたGraphQL APIへ

標準的なPrismaのユースケースを簡単に見て、ブログアプリ用のGraphQL APIを簡単な手順で迅速に構築する方法を見てみましょう。これから行うことは次のとおりです。

  1. TypeScriptでPrismaプロジェクト(無料のデモデータベースを使用)をセットアップします。
  2. モデルを定義し、データベースを移行して、Prismaクライアントを生成します。
  3. nexus-prisma経由で完全なCRUD GraphQL APIを公開します。
  4. nexus-prisma経由でGraphQL APIをカスタマイズします。

続けて操作する場合は、Prisma CLIがインストールされている必要があります。

1)TypeScript、nexusnexus-prismaでPrismaプロジェクトをセットアップします。

このセクションでは、主にプロジェクトのセットアップについて説明します。コードを一緒に記述しない場合はスキップしてもかまいません。それ以外の場合は、以下のセクションを展開してください。

Prisma CLIを使用して、シンプルなPrismaプロジェクトを作成します。

インタラクティブプロンプトで、次のオプションを選択します。

  1. デモサーバーを選択します(Prisma Cloudで無料&ホストされているデモデータベースが含まれています)。
  2. ブラウザでPrisma Cloudで認証します(必要な場合)。
  3. ターミナルに戻り、提案されたすべての値を確認します。

デモサーバーの代替として、Dockerを使用してPrismaをローカルで実行することもできます。

次に、nexus-prismaワークフローを構成する必要があります。次の依存関係を追加します(myblogディレクトリ内)。

次に、prisma.ymlの最後に次の2行を追加します。

これにより、モデルを変更するたびに、Prismaクライアントと生成されたnexus-prisma CRUD構成要素が更新されるようになります。

TypeScriptを使用しているので、tsconfig.jsonをすばやく追加しましょう。

最後に、開発に使用するstartスクリプトを追加します。バックグラウンドでファイルを監視し、コードを記述するときに生成されたSDLとNexus型定義を更新する開発サーバーを起動します。これをpackage.jsonに追加します。

2)モデルを定義し、データベースを移行して、Prismaクライアントを生成します。

prisma initコマンドは、datamodel.prismaにデフォルトのUserモデルを作成しました。ブログアプリケーションを構築しているので、モデルをアプリケーションドメインに合わせて調整しましょう。

次に、データモデルを適用してデータベースを移行する必要があります。次のコマンドを使用すると、datamodel.prismaで定義された各モデルは、基盤となるデータベースのテーブルにマッピングされます。

以前にprisma.ymlpost-deployフックを構成したため、PrismaクライアントとCRUD構成要素は自動的に更新されます。

3)nexus-prisma経由で完全なCRUD GraphQL APIを公開します。

プロジェクトの初期段階では、APIによって完全なCRUD機能が公開されていると便利なことがよくあります。より制約の厳しいAPI要件は、通常、時間の経過とともに明らかになります。nexus-prismaは、完全なCRUDからカスタマイズされたAPI操作に移行するための簡単な方法を提供することで、それを完全に考慮しています。

定義されたモデルの完全なCRUDを公開するGraphQL APIから始めましょう(これには、フィルター、ページネーション、ソートが含まれることに注意してください)。index.tsという新しいファイルを作成し、次のコードを追加します。

この短いチュートリアルでは、ファイル構造にあまり注意を払っていません。適切なセットアップとモジュール化されたスキーマについては、graphql-authの例を確認してください。

npm run startを実行した後、http://localhost:4000でGraphQLサーバーのGraphQL Playgroundを開くことができます。上記で記述したわずかなコードで、すでに本格的なGraphQL CRUD APIを自由に使用できます。

クエリの例

ミューテーションの例

これはどのように機能するのでしょうか?nexus-prisma-generateは、Prismaモデル(CRUD構成要素)のCRUD APIを提供するGraphQLスキーマを生成しました。このGraphQLスキーマは、OpenCRUD仕様に従っています。prismaObjectType関数を使用すると、そのスキーマの操作を公開およびカスタマイズできるようになります。

prismaObjectTypeprismaFieldsはホワイトリストアプローチを使用します。つまり、公開するフィールドを明示的にリストする必要があります。ワイルドカード演算子*は、すべてのフィールドを含みます。

Expose full CRUD GraphQL API via nexus-prisma

4)nexus-prisma経由でGraphQL APIをカスタマイズします。

このセクションでは、nexus-prismaのCRUD GraphQL APIをカスタマイズする方法を学びます。具体的には、次のことを行います。

  1. Userモデルからフィールドを非表示にします。
  2. Postモデルに計算フィールドを追加します。
  3. createPostおよびupdatePostミューテーションを非表示にします。
  4. 2つのカスタムcreateDraftおよびpublishミューテーションを追加します。

4.1)Userモデルからフィールドを非表示にします。

このセクションでは、Userモデルからemailフィールドを非表示にします。

モデルをカスタマイズするには、prismaObjectType関数を適用し、オプションとしてdefinition(t)関数を渡す必要があります。

モデルtprismaFieldsを呼び出すことにより、公開されるフィールド(およびその引数)をカスタマイズできます。emailがリストに含まれていないため、GraphQL APIから削除されます。

Hide a field from the User model

変更を適用するには、makePrismaSchema内のtypes配列にUserを明示的に渡す必要があります。

エディターは、生成されたCRUD構成要素に基づいて、prismaObjectTypeおよびprismaFieldsに渡すものを提案できることに注意してください。これは、prismaObjectType('')と入力してctrl + spaceを押すと、生成されたすべてのCRUD構成要素の名前が提案されることを意味します。t.prismaFields([''])を呼び出すと、tのフィールドが提案されます。

4.2)Postモデルに計算フィールドを追加します。

nexus-prismaを使用した新しいコードファーストアプローチにより、Prismaモデルに計算フィールドを簡単に追加することもできます。Postに常にタイトルをすべて大文字で返すフィールドを追加するとします。その実装方法を次に示します。

graphql-nexusから提供されるt.string(...) APIを使用して、モデルに新しいフィールドを追加します。これは計算フィールドであるため(nexus-prismaによって自動的に解決することはできません)、リゾルバーもアタッチする必要があります。

Customize the GraphQL API via nexus-prisma

前と同様に、カスタマイズされたPostモデルをtypes配列に明示的に追加する必要があります。

4.3)createPostおよびupdatePostミューテーションを非表示にします。

Userモデルからemailフィールドを非表示にしたのと同じ方法で、生成されたnexus-prisma CRUD構成要素の一部であるQuery/Mutationタイプから操作を非表示にすることもできます。

createPostupdatePostを非表示にするには、オプションとしてdefinition(t)prismaObjectTypeに再度渡す必要があります。タイプでprismaFieldsを呼び出すと、保持するすべてのフィールドを明示的にリストする必要があることに注意してください(空の配列は「操作を保持しない」と解釈されます)。

生成されたCRUD GraphQL APIには、バッチ操作とupsert操作も含まれていますが、ここでは簡潔にするために除外しています。

4. 2つのカスタムcreateDraftおよびpublishミューテーションを追加します。

最後に、GraphQL APIに2つのカスタムミューテーションを追加します。それらのSDL定義がどのように見えるはずかを次に示します。

これらのミューテーションを実装するには、Mutationタイプに2つのフィールド(nexus APIからt.field( ... )を呼び出すことによって)を追加する必要があります。

これを機能させるには、nexusパッケージからstringArgidArgをインポートしてください。

GraphQL Nexusは、GraphQLスキーマのSDLバージョンも生成します。./generated/schema.graphqlにあります。最終バージョンのGraphQL APIは次のようになります。


コードファーストGraphQL記事からの3つの重要なポイント

これは、コードファーストGraphQLサーバー開発に関する記事シリーズの最後の部分でした。

GraphQL Nexusnexus-prismaプラグインは、2年以上にわたってGraphQLエコシステムの活発な貢献者であることから収集した学習内容を実装しています。SDLファーストアプローチで多くの問題を発見した後、現在出現している新しいコードファーストツールに非常に興奮しています。

GraphQL Nexus(およびTypeGraphQLなどの他のコードファーストアプローチ)は、GraphQLスキーマが将来どのように構築されるかを劇的に変えると強く信じています。

シリーズからの主なポイントを次に示します。

  1. コードファーストアプローチを使用すると、追加のツールを必要とせずに(「必要なツールはプログラミング言語だけ」)、言語に特有の方法でGraphQLサーバーを構築しながら、通信ツールとしてのSDLの利点を保持できます。
  2. GraphQL Nexusを使用すると、開発者は柔軟でタイプセーフなAPIでスキーマを構築できます。開発者は、オートコンプリートとビルド時のエラーチェックのおかげで素晴らしい体験を得られます。
  3. nexus-prismaプラグインは、Prismaモデルの上に構築され、開発者が自動生成されたCRUD構成要素を公開およびカスタマイズすることにより、GraphQL APIを構築できるようにします。

今日nexus-prismaをお試しください 🙌

nexus-prismaを試すにはいくつかの方法があります。ドキュメントのはじめにセクションに従うか、TypeScript GraphQLの例をご覧ください。

GitHub issueを開くか、Slackでお問い合わせいただくことで、フィードバックをお寄せください。


nexus-prismaプラグインでの彼の素晴らしい仕事に対して、オープンソースエンジニアのFlavian Desverneに心から感謝します 💪✨

次の投稿をお見逃しなく!

Prismaニュースレターにサインアップしてください。