graphql-codegenでgraphqlのendpointからTypescriptの型定義、さらにreact-apollo-hooksも自動生成

# 問題
Typescriptを使ってgraphqlは型定義が煩雑になる

- graphqlのschemaで全て定義してるのに
- 使う側のTypescriptで再度同じ定義する必要がある（variablesだったり、戻り値のオブジェクト定義だったり）

これをendpointのschemaや、実際に使っているgraphqlクエリから型定義を自動生成しようというのが↓

# GraphQL Codegen
https://graphql-code-generator.com/docs/getting-started/

## 必要になるもの

1. schema
    - graphqlのendpoint（apollo-clientで接続するURL）
    - [GraphQL Introspection JSON][1]でのschemaファイル
    - [schema][2]ファイル
    - のいずれか

2. 使用する実際のgraphqlクエリファイル
    - https://graphql-code-generator.com/docs/getting-started/documents-field
    - （通常 `const query = gql...` で定義するものを~~ファイルへ書き出す必要がある~~）
    - 書き出さなくても、`documents: src/**/*.{ts,tsx}`のように設定してコード内のgraphqlクエリを読み出せるみたい
    - 実際には生成される`useHook`を使う事になり、そうなるとクエリをコード内に書く必要がなくなるので、どうしても最後には別ファイルにクエリを書き出す事になると思うが...


```graphql:UserInfo.graphql　例
query UserInfo{
  name
  age
}
```

## 始め方

ドキュメントに沿ってやってみたが実際にはエラーで止まる箇所があるので、以下のように理解してやってみた。

まずは必要なパッケージのインストール

```bash
$ yarn add graphql
$ yarn add -D @graphql-codegen/cli
```

その後は次のコマンドで`codegen.yml`を自動生成できるが、これで自動生成されたものでは実際にはうまく動かないので、スキップ（v1.0.7現在）

```bash
$ graphql-codegen init # やらない
```

自分で`codegen.yml`を作る

```yaml
overwrite: true # 出力するファイルを毎度上書きする
schema: "http://localhost:3000/graphql" # 自分のendpoint
documents: "**/*.graphql" # クエリファイル 拡張子は変えても良い
generates:
  src/generated/graphql.ts: # 出力するファイル名 
                            # 出力先、ファイル名は任意だが、拡張子はtsまたはtsx
    plugins: # 必要となるプラグイン
      - "typescript"
      - "typescript-operations"
      - "typescript-react-apollo"
    config:
      # 下の3つはtypescript-react-apolloのオプション
      withHOC: false # HOCは要らないので
      withComponent: false # falseなので出力ファイル拡張子が.tsでもいい。
                           # このオプションを設定しないとデフォルトtrueなので、.tsx拡張子にしろとエラーが出る
      withHooks: true # 上のdocumentsの設定があればこれでhookが自動生成される

```

参考：

- https://graphql-code-generator.com/docs/getting-started/codegen-config
- https://graphql-code-generator.com/docs/getting-started/schema-field
    - URL
    - GraphQL Introspection JSON https://graphql.org/learn/introspection/
    - graphql schema ファイル https://graphql.org/learn/schema/
- https://graphql-code-generator.com/docs/getting-started/documents-field
- https://graphql-code-generator.com/docs/plugins/typescript
- https://graphql-code-generator.com/docs/plugins/typescript-operations
- https://graphql-code-generator.com/docs/plugins/typescript-react-apollo

pluginsに挙げたpackageはまだインストールしていないので、インストールする

```bash
yarn add -D @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-react-apollo

```

`codegen.yml`の`documents`に書いたパスへクエリファイルを配置する
（このクエリファイルが無いと`withHooks:true`でもhookは出力されないので注意）

```graphql:例　src/documents/UserInfo.graphql
query UserInfo{
  name
  age
}
```

最後に`yarn generate`と簡単に出来るようにscriptを追加

```json:package.json

  "scripts": {
    "generate": "graphql-codegen --config codegen.yml"
  }

```

そして実行

```bash
yarn generate

```

そうすると`src/generated/graphql.ts`が出力される
これにより今までTypescript側でも行っていた型定義が不要になる（importすればいいだけになる）
さらに`documents`に書いたクエリ毎の`useHook`も出来上がっているので、下のように簡単にgraphqlが使えるようになる

## 使用例

```tsx
import { useGeneratedQuery } from "./src/generated/graphql"

...
...

export default () => {
  const query = useGeneratedQuery()

  if(query.loading){
    return 
  }

  return (
    <div>{query.data.name}</div>
  )
}
```

このhookに関しては[デフォルト][3]（*hooksImportFrom (string, default value: react-apollo-hooks)*）として`react-apollo-hooks`を使っているので、実際に使用する際には

```bash
$ yarn add react-apollo-hooks
```

が必要になる

[1]: https://graphql.org/learn/introspection/
[2]: https://graphql.org/learn/schema/
[3]: https://graphql-code-generator.com/docs/plugins/typescript-react-apollo