タイプスクリプトとPrismaモデルによるGraphSQLコードジェネレータ


This article was published on 2021-12-19 by @ The Guild Blog


導入


Graphqlあなたの人生を容易にすることができますいくつかの素晴らしいツールがあります.それらのツールの一つはGraphQL Code-Generator これは、あなたのGraphSQLスキーマに基づいて(より多くの)型を作成するのに役立ちます.
あなたがGraphSQLサーバを作成しているならば、あなたはたぶん、それのようなものでそれの背後にデータベースを持っていたいでしょうPrisma .
だから、どのように使用することができますPrisma あなたのデータベースのために、まだGraphSQL Codegenを使ってください?この記事は使用方法を扱っているPrisma with GraphQL Code-Generator , そして、開発者の経験を高める設定フラグ.

プリマ


Prismaとは


Prisma オープンソースは次世代ORMを完全にタイプします.以下の部分からなる.
Prismaクライアント:ノードの自動生成とタイプセーフクエリビルダ.JSとタイプスクリプト
Prisma migrate :マイグレーションシステム
Prisma Studio:GUIでデータベース内のデータを表示および編集する
それぞれのPrismaプロジェクトには、そのモデルを定義するために使用されるスキーマがあります.
Prismaツールキットからツールを使用するすべてのプロジェクトは、Prismaスキーマファイルから始まります.
Prismaスキーマは、開発者が直感的なデータモデリング言語でアプリケーションモデルを定義することができます.

なぜPrisma?


Prismaの主な目標は、アプリケーション開発者をデータベースで作業するときにより生産的にすることです.
Prismaがこれを実現する方法のいくつかの例を示します.
  • 関係データのマッピングの代わりにオブジェクトにおける思考
  • 複雑なモデルオブジェクトを避けるためのクラスではない
  • データベースとアプリケーションモデルのための真理の単一ソース
  • 一般的な落とし穴と反パターンを防ぐ健康的な制約
  • 正しいことを簡単にする抽象化(「成功のピット」)
  • コンパイル時に検証できるタイプセーフなデータベースクエリ
  • ので、開発者は、アプリケーションの重要な部分に焦点を当てることができます

  • ドキュメントを検索するのではなく、コードエディターで自動補完
    A tutorial about how to get started with Prisma
  • グラフィカルジェネレータ


    The GraphQL Code-Generator GraphSQLプロジェクトを使用してSafteyを作成する簡単な方法です.
    それはあなたのGraphSQLスキーマに基づいて自動的にTypeScriptタイプを生成します.これは間違いを書く可能性を減らすため、非常に有用ですし、ビルド時にバグを見つけることができます.
    たとえば、CodeGenのないJavaScript/typescriptリゾルバの例です.
    const resolver = {
      Query: {
        feed: async (
             parent: unknown,
             args: {
             filter?: string;
             skip?: number;
             take?: number;
             },
             context: GraphQLContext
           ) => {...}
      }
    }
    
    しかし、CodeGenを使用すると、手動型が不要になります.
    import { Resolvers } from './generated/graphql'
    
    const resolvers: Resolvers = {
      Query: {
        feed: async (parent, args, context) => {
          // ...
        }
      }
    }
    
    ご覧のように、リゾルバが型化されたので、各リゾルバの型を定義する必要はありません.

    If you are new to GraphQL-Codegen, you can follow a tutorial about how to get started with GraphQL codegen

    You can also .


    完全型付けコードを書く利点

  • より良いコード補完と構文強調表示.
  • コード中にIDE内のヒントやドキュメントを取得できます.これは特定の関数/メソッドの振る舞いについて誤った仮定をする可能性を減らします.
  • 物事を見つけるのは簡単です.任意の変数や関数については、IDEを離れることなく簡単にクラス定義に移動でき、プロジェクトのディレクトリ構造について何も知りません.逆に、任意のクラスまたは関数の定義については、そのクラスまたは関数を使用してコードを使用してIDEを離れることなく簡単に参照できます.(静的にタイプされた言語はIDEがこれを行うのを容易にします).
  • 静的型付けは、リレーショナルデータベースや静的な型にも依存する他のシステムで動作するようになります.コンパイル時により不適切な型のミスマッチをキャッチできます.
  • いくつかの種類のエラーの可能性を減らすことができます.たとえば、動的に型付けされた言語では、ユーザー入力をサインインしても気にしないなら、(例えば)文字列“8”で番号10を追加しようとするような奇妙なものをしてしまうことができます.
  • GraphSQL CodegenとPrismaを一緒に使う


    PrismaとGraphSQL Codegenの利点を学習した後、一緒に両方を使用することがあります!しかし、いくつかの問題点

    名前の衝突


    prismaモデルとgraphqlモデルは互いに衝突する可能性がある.
    これは、GraphSQL CodeGenが自動的にGraphSQLスキーマから型を使用しており、Prismaが自動的にPrismaモデルから型を生成するためです.
    あなたのGraphSQLスキーマが使用されている場合type User { ... } そして、あなたのPrismaモデルはmodel User { } , あなたは命名紛争があるかもしれません.

    データベースの種類グラフタイプ


    データベースの型で、GraphSQL型と同じです.あなたのGraphSQL層では、あなたがデータベースに持っているより異なった制限/制約を受けるかもしれません.
    たとえば、いくつかのPRISMA演算は、フィルタリングとPaginatingのための引数を取得します.現在、あなたのGraphSQLスキーマでこのタイプのフィルタを持っているなら、次のようになります.
    type Query {
      feed(filter: String, skip: Int, take: Int): Feed!
    }
    
    ご覧の通り、引数filter , skip and take はNULLを返します.
    これで問題は?
    さて、フィルタリングとPaginating Prismaは値を持っているか、またはundefined , ではなくnull .
    これはCODEGENの型がデフォルトで値を使うためですnull できればnull ( null | undefined | T ).

    どうやってこれを修正する?


    さて、最初の問題については、コードジェネレータはオプションmappers .
    マッパーを使用して別の1つのタイプをマップするオプションを提供します.
    このオプションは、CodeGenスキーマから生成される既定の型の代わりにCodeGenにPrismaモデルを使用できるようにするために、私たちの問題を解決します!
    番目のFIXはinputMaybeValue .
    null可能な型は、おそらくGraphSQL CodeGenで表されます.The inputMaybeValue , あなたは引数をすることができますタイプを変更することができます!
    上記の2つの設定フラグを使用すると、どのようなタイプのタイプを生成するのか、そしてどのようにGraphSQL型をPrismaモデルにマップするかをGraphSQL CodeGenに伝えることができます

    マッパを使う


    マッパは実際に使いやすいです、あなたがする必要があるすべてはあなたにそれらを追加することですcodegen.yml !
    Exapmleのために、私は私が呼ばれるprismaモデルを持っていると言うことができますUser , また、私のGraphSQLスキーマもtype User .
    データベースで動作する私のプロジェクトでは、GraphSQLの代わりにPrismaモデルを使用する必要がありますので、私のユーザモデルをPrismaからGraphSQLのユーザータイプにマップする必要があります.
    以下に例を示します:
    schema: http://localhost:3000/graphql
    documents: ./src/graphql/*.graphql
    generates:
      graphql/generated.ts:
        plugins:
          - typescript-operations
          - typescript-resolvers
      config:
        mappers:
          User: .prisma/client#User as UserModel
    
    の下にmappers , あなたは、我々がGraphqlを取るのを見ることができますUser を入力し、自動的にPrismaによって作成されたエクスポート型を使用するように設定します.
    我々はそれを命名するように設定したUserModel , したがって、それはGraphSQLのGraphSQL定義と衝突しませんUser 種類

    InputMayBeValueの使用

    inputMaybeValue かなり簡単に使用するだけで下に追加されますcodegen.yml 設定ファイル:
      schema: http://localhost:3000/graphql
    documents: ./src/graphql/*.graphql
    generates:
      graphql/generated.ts:
        plugins:
          - typescript-operations
          - typescript-resolvers
      config:
        mappers:
          User: .prisma/client#User as UserModel
        inputMaybeValue: undefined | T
    
    では、デフォルト値inputMaybe ( null引き可能な引数の型)undefined or T , GraphSQL間の簡単な型互換性につながるinput 引数とPrisma SDKの要件.

    今何?


    ここで、GraphSQL CodegenとPrisma Codegenを実行し、完全に型付けされたリゾルバを取得します.以下に例を示します:
    import { Resolvers } from './generated/graphql'
    
    const resolvers: Resolvers = {
      Query: {
        user: async (parent, args, context) => {
          // Codegen will generate Resolvers type, and
          // will expect you to return here an object of
          // Prisma's User model.
    
          return context.prisma.user.findOne({ id: args.id })
        }
      },
      User: {
        name: (user) => {
          return `${user.first_name} ${user.last_name}`
        }
      }
    }