Table of Contents
セットアップ
$ npm install --save-dev eslint eslint-plugin-graphql
設定ファイルに関しては各プロジェクトによって適したものを設定してください。今回はここの説明は省きます。(参考URL: https://eslint.org/docs/user-guide/getting-started)
GraphQLスキーマ
今回ESLintのベースとなるスキーマは以下になります。
type Query {
todos: [Todo]
}
type Todo {
id: ID!
title: String
body: String
done: Boolean
}
このスキーマ情報をESLintへ設定を行い、クライアント側で使われているクエリが正しいものなのかチェックを行います。
スキーマ情報の取得
ESLintへスキーマ情報を読み込ませるにはGraphQLの Introspection 結果が書かれたjsonファイルが必要です。
このファイルを生成する方法の一つに Apollo CLI を使う方法があります。
Apollo CLI色々できるので他の機能も試してみるといいかもしれません。
まずはApollo CLIをグローバルにインストールします。
$ npm install -g apollo
インストールが完了したら、GraphQLサーバーのエンドポイントを指定してスキーマ情報が書かれたschema.jsonを生成します。
$ apollo client:download-schema schema.json --endpoint="[自分のGraphQLエンドポイント]"
すると、以下のようなschema.jsonファイルが出力されます。
{
"__schema": {
"queryType": {
"name": "Query"
},
"mutationType": null,
"subscriptionType": null,
"types": [
{
"kind": "OBJECT",
"name": "Query",
"description": "",
"fields": [
{
"name": "todos",
"description": "",
"args": [],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "Todo",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [],
"enumValues": null,
"possibleTypes": null
},
.
.
.
}
eslint-plugin-graphqlの設定
GraphQLサーバーのスキーマ情報が取れたので、あとはESLintの設定を書くのみです。
クライアントアプリはReactやVueなどなんでもいいですが、リクエストに使用するクエリは別ファイルなどに切り出していることが多いと思います。
eslint-plugin-graphqlがサポートしている拡張子は .js、.gql、.graphqlとなっています。
今回でいうと以下のようなクエリになります。
// todos.js
import gql from 'graphql-tag'
export const GET_TODOS = gql`
query GetTodos {
todos {
id
title
}
}
`
このGET_TODOSをApollo Clientに読み込ませるなどしてサーバー側との通信を行うと思います。
それでは先ほど用意したschema.jsonを利用してESLintルールを記述します。
// .eslintrc.js
module.exports = {
.
.
.
rules: {
"graphql/template-strings": ['error', {
schemaJson: require('./schema.json')
}],
"graphql/named-operations": ['warn', {
schemaJson: require('./schema.json'),
}],
"graphql/capitalized-type-name": ['warn', {
schemaJson: require('./schema.json'),
}]
},
plugins: [
'graphql'
]
};
今回は上記のように設定しました。詳しい設定方法は公式リポジトリで確認できます。
基本的にgraphql/template-stringsを設定していれば良いですが、オプションで
- graphql/named-operations: オペレーション名を必須にする
- graphql/capitalized-type-name: 型名の最初は大文字にする
などが設定できます。今回はwarningを出すだけにしています。
次にeslintコマンド省略のためにpackage.jsonに設定します。
{
.
.
"scripts": {
.
.
"lint": "eslint . --ext .js"
},
}
--extオプションでLint対象となるファイル拡張が指定できます。今回は.jsのみにしました。
試してみる
設定が完了したのでコマンドを実行してみます。
$ npm run lint
うまくいけばtodos.jsに書かれたクエリには問題ないのでエラーも出ずに終了します。
試しに誤ったクエリにtodos.jsを書きかえてみます。
// todos.js
import gql from 'graphql-tag'
export const GET_TODOS = gql`
query {
todos {
id
titlw
}
}
`
このようにオペレーション名をなくし、フィールド名も title
を titlw
にtypoした状態でLintしてみます。
$ npm run lint
/my-project/todos.js
4:3 warning All operations must be named graphql/named-operations
7:7 error Cannot query field "titlw" on type "Todo". Did you mean "title"? graphql/template-strings
それぞれerrorとwarningがちゃんとでました。
まとめ
ESLintを使ってクライアントアプリで書かれたクエリに対してのバリデーションチェックを行う設定を紹介しました。
これをCIでeslintコマンドを実行させたり、VSCodeなどのエディタでESLint拡張を導入して、事前にクエリエラーに気づけ、安全なGraphQL開発ライフを送ることができるようになりました。
しかし、これだけではMutationのネストされたInputタイプまではチェックすることはできません。
その場合はサーバー側を巻き込んでの統合テストや 前回の記事 で書いたようなモックサーバーを利用したテストを書くことをお勧めします。