GraphQL Scalars便利だなぁ🚀
こんにちは、yunbooです。
今回はThe Guildという組織が開発しているGraphQLエコシステムのGraphQL Scalarsについての記事です。
余談なんですが、The Guildは今回紹介するGraphQL Scalars
以外にも様々なエコシステムを提供しており、その代表格としてはGraphQL Code Generator
があると思います。
他にも、たくさん便利なものを提供しているので、もろもろ見てみると役に立つ情報が得られたり、面白いと思います。
さて、本題ですがGraphQL Scalarsについて説明する前の前提知識として、GraphQLのScalar型について軽く説明します。
Scalar型とは
GraphQLにはスキーマを定義する際に型が存在しますが、Scalar型とは
- プリミティブな値を表すもの
- フィールドが最終的に変換される、それ以上に分割出来ない型
GraphQLがデフォルトで用意しているのは、
- Int: 符号付き 32 ビット整数
- Float: 浮動小数点値
- String: UTF-8 文字シーケンス
- Boolean: true or false
- ID: オブジェクトの一意な識別子
の5つです。
さらに、よりスキーマの表現力を広げるために、Custom Scalarというのもあります。
Custom Scalar
先ほどの5つでほとんどのユースケースに対応はできますが、Custom Scalar型を使いより強力な型チェックや検証ができるようになります。
例えば、Custom Scalarの例として、Email型で紹介します。
クライアントがフォームでメールアドレスを入力し、入力された値に対しバリデーションで、文字列がが正しいメールアドレスの形式なのか確認します。
バリデーションを経て正しい形でクライアントからGraphQLサーバーにMutationで送信します。
この際に、スキーマにemail: String!
で定義していると正しい形式で送られてきているメールアドレスの情報が失ってしまい、ただのString型になってしまいます。
input LoginInput {
email: String! <-- ここ
password: String!
}
type Mutation {
login(input: LoginInput!): LoginPayload
}
ここで、email: Email!
と定義してあればGraphQLでも正しくチェックし適切な情報をサーバーに送ってくれます。
input LoginInput {
email: Email! <-- ここ
password: String!
}
type Mutation {
login(input: LoginInput!): LoginPayload
}
他にもCustom Scalarのいいところで、今回の説明だとemailというフィールド名なので、仮にString型だとしてもメールアドレスであることは見てわかると思いますが、例えばidフィールドを持った場合に、連番のidなのか、それともまた違ったidの形式なのかわからないと思います。
ですが、id: UUID!
であればこのidはID型という抽象的な型ではなく、UUID型より具体な型だとスキーマから型名だけで意図を伝えることもできます。
Custom Scalarを使いよりスキーマの表現の幅を広げることができるようになりました。
ただ、デフォルトで用意されている訳ではないのでCustom Scalarを一から自分で実装する必要があります。
実装自体にはそれなりのコストが掛かってきます。
そこで、GraphQL Scalars
の出番です。
GraphQL Scalarsとは
様々なユースケースに沿ったCustom Scalarのライブラリです。
先ほどの説明で使用したメールアドレスのCustom Scalarももちろん用意されています。
他にもUUID
であったり、JWT
など幅広く用意されています。
興味ある方はドキュメントのScalarsの所を見てもらえればなと思います。
今度は逆にCustome Scalarで定義した型をクライアント側でも使いたいと思います。
そこは、現状だとスキーマを見てGraphQL Code Generatorがよしなにやってくれるわけではなくて(自分が知っている限りだと)、以下のようにTypeScriptで独自の型を実装しGraphQL Code Generatorのプラグインを使いつつ当てはめていく必要があります。
export type EmailAddress = string & { __type: "EmailAddress" };
export const isEmailAddress = (
str: string
): str is EmailAddress => {
const EMAIL_ADDRESS_REGEX =
/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
return EMAIL_ADDRESS_REGEX.test(str);
};
こちらに関しては、下の記事で、より詳細な説明がされいるので参考になりました🙋
ただ、自作するのは多少めんどくさい部分でもあるので今後GraphQL Code Generatorがプラグインなどを用意してくれることに期待しています。。。
最後に
GraphQL Scalarsの説明というより、Custom Scaralsの説明のが長々としてしまいましたが、そのCustom Scaralsを使うためにGraphQL Scalarsを使うと便利だよというのが今回伝えたかったことでした。
Discussion