GraphQL Code Generatorってどんなコードを生成してくれるの？

GraphQLを使う上で、GraphQL Code Generatorというツールがとても便利で、色々なコードを生成してくれるというのは知っていました。
実際、普段は設定されていたのものを使っているのですが、改めてどんなツールなのかをちゃんと理解していないなと思い、調べてみました。

## GraphQL Schema

GraphQL Code Generatorがコードを生成するベースとなるのはGraphQL Schemaです。

https://graphql.org/learn/schema/

フロントエンドでTypeScriptを使っていると、一見TypeScriptにも見えてしまうのですが、これはGraphQL schema languageです。

```graphql
type Human implements Character {
  id: ID!
  name: String!
  friends: [Character]
  appearsIn: [Episode]!
  starships: [Starship]
  totalCredits: Int
}
```

GraphQL Schemaは言語に依存しない独自のシンタックスのため、GraphQLサーバーの実装言語を特定のものに制限しません。

今回説明するクライアント側のコードは、このスキーマがベースとなって生成されます。

## クライアント側のコード生成

GraphQL Code GeneratorではPluginを使うことで様々なコードを生成することができます。

今回はクライアント側でよく使いそうなものをいくつか紹介していきます。

## 事前準備

デモとしてSchemaが必要なので、GitHub GraphQL APIのスキーマを使用します。
以下のページからダウンロードできるので、ダウンロードしてリポジトリに配置します。

https://docs.github.com/ja/graphql/overview/public-schema

ちなみに、今回私がいじってみた環境はこちらです。

@graphql-codegen/cli: v2.6.2

https://github.com/kyntk/q-graphql-codegen

## 1. GraphQL Schemaの型定義

GraphQL Schemaを元に、クライアント側で使う型定義ファイルを生成します。

pluginは`TypeScript`を使用します。

https://www.graphql-code-generator.com/plugins/typescript

以下のようにcodegen.ymlを設定すると、`src/generated/types.ts`にGitHub GraphQL APIのスキーマを元に型定義が生成されます。

```yml:codegen.yml
overwrite: true
schema: './github.schema.graphql'
documents: 'src/graphql/*.gql'
generates:
  src/generated/types.ts:
    plugins:
      - typescript
```

中身を見てみると、オブジェクトの型や、スカラー、enum、クエリの引数などの型が生成されていました。

詳しくはこちらに生成したファイルを置いているので、見てみてください。

https://github.com/kyntk/q-graphql-codegen/blob/main/src/generated/types.ts

## 2. オペレーションの型

これは、クライアント側で定義したquery, mutation, subscription, fragmentの型です。
`TypeScript Operations`を使います。

https://www.graphql-code-generator.com/plugins/typescript-operations

例えば、以下のようなクエリを定義しておきます。

```graphql
query GetViewer {
  viewer {
    login
  }
}
```

そして設定を追加してコードを生成してみると以下のようになりました。

```ts
export type GetViewerQueryVariables = Types.Exact<{ [key: string]: never }>

export type GetViewerQuery = {
  __typename?: 'Query'
  viewer: { __typename?: 'User'; login: string }
}
```

今回のQueryには引数が無いこと、Queryを実行した時に上記のような型でデータが帰ってくることが分かります。
これを使うことで型安全なコードが実装できそうです。

## 3. React hooksの生成

`TypeScript React Apollo`を使うとhooksを生成することもできます。

https://www.graphql-code-generator.com/plugins/typescript-react-apollo

```ts
import { useQuery } from '@apollo/client'
import type { GetViewerQuery } from './generated/operations'
import GetViewer from './graphql/GetViewer.gql'

const { data } = useQuery<GetViewerQuery>(GetViewer)
```

1, 2までで生成したコードを使って上記のようにしても良いのですが、このpluginを使うと`useGetViewerQuery`というhooksが作られ、

```ts
import { useGetViewerQuery } from './generated/graphql'

const { data } = useGetViewerQuery()
```

上記のコードだけで済むので記述量を減らすことができます。

実装は単純に`useQuery`をラップしたもののようでした。

```ts
export function useGetViewerQuery(
  baseOptions?: Apollo.QueryHookOptions<
    Types.GetViewerQuery,
    Types.GetViewerQueryVariables
  >
) {
  const options = { ...defaultOptions, ...baseOptions };
  return Apollo.useQuery<Types.GetViewerQuery, Types.GetViewerQueryVariables>(
    GetViewerDocument,
    options
  );
}
```

(補足: 調べていく中で、以下のような記事もあったので、使用を絶対おすすめするというものではありません)

https://qiita.com/shinnoki/items/576277184de0e89cab97

これも今後使ってみようと思います。

## その他

その他にも様々なpluginがあります。

https://www.graphql-code-generator.com/plugins

今回紹介したのはクライアント用でしたが、バックエンド用や、React以外のライブラリ用のpluginもあります。

また、[GraphQL Code Generatorのサイトトップ](https://www.graphql-code-generator.com)にはLive Exampleがあり、具体的にどんなコードが生成されるのかイメージしやすいものもあるので、ぜひ見てみてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143317/02f64139-2722-ee2d-20fb-1a2fa3ebab51.png)

今回見きれなかった部分もあるので、もっと色々触ってみようと思います！

## 参考

- https://www.graphql-code-generator.com
- https://graphql.org/learn/schema/
- https://qiita.com/shinnoki/items/576277184de0e89cab97
- https://qiita.com/suin/items/de0afe49f95990083ffc
- https://docs.github.com/ja/graphql/overview/public-schema