GraphQL の色々なスキーマ表現について - GraphQL Schema Language や schema.json
(=˘ ꒳ ˘=) GraphQL のスキーマ表現いろいろ多すぎ...
で Introspection について眺めたら GraphQL のスキーマ表現について整理できてきたのでまとめてみます。
GraphQL のスキーマ表現
GraphQL Schema Language
type Query { hello: String! }
のようなDSLのことを指します。GraphQL SDL(Schema Definition Language) とも呼ばれています。
人が一番読みやすい形式といったらこれですね。
GraphQL.js の buildSchema
に渡されたり graphql-tools の makeExecutableSchema
に typeDefs
として渡されます。
GraphQL.js の GraphQLSchema
import { GraphQLSchema, GraphQLObjectType } from 'graphql' const schema = new GraphQLSchema({ query: new GraphQLObjectType({ name: 'rootQuery', fields: { hello: { type: GraphQLString, }, }, }),
のような GraphQLSchema
インスタンスを直接コンストラクトする表現。
resolve
定義など何でもできますが、手作業では書きたくないですね。
ある程度 GraphQL に慣れていてもそう思いますし、そうでないならなおさらだと思います。
Introspection Result
apollo-codegen のようなツールが schema.json のように出力するファイルの中身がこれにあたります。 実態はリソースとなるAPIに対する Introspection の結果が書き出されたものです。 この Introspection に用いるクエリはintrospectionQuery として定義されています。 定義内容はとても長いので手作業では書きたくないですね。
簡単なコードでこのクエリを実行してみます。
import { graphql, buildSchema, introspectionQuery } from 'graphql' const schema = buildSchema(` type Query { hello: String! } `) graphql(schema, introspectionQuery).then(console.log)
これを実行すると schema.json
の中身としてよく見かける
{ data: { __schema: { queryType: [Object], mutationType: null, subscriptionType: null, types: [Array], directives: [Array] } } }
という値が得られます。
AST Schema
GraphQL Schema Language をパースしたAST(抽象構文木)です。
ライブラリ利用者としてはあまり利用する機会はありませんが、何気なく console.log
した結果によく出てくる気がします。
import { parse, buildASTSchema } from 'graphql' const typeDefs = ` type Query { hello: String! } ` const ast = parse(typeDefs)
を実行すると
{ kind: 'Document', definitions: [ { kind: 'ObjectTypeDefinition', description: undefined, name: [Object], interfaces: [], directives: [], fields: [Array], loc: [Object] } ], loc: { start: 0, end: 33 } }
という AST Schema が得られます。
スキーマ表現間の変換
これらのスキーマ表現は graphql と graphql-tools の各種ユーティリティである程度の変換が可能となっています。
- graphql
buildClientSchema
: Introspection Result →GraphQLSchema
buildSchema
: GraphQL Schema Language →GraphQLSchema
printSchema
:GraphQLSchema
→ GraphQL Schema Languageparse
: GraphQL Schema Language → AST SchemabuildASTSchema
: AST Schema →GraphQLSchema
- graphql-tools
makeExecutableSchema
: GraphQL Schema Language + resolve/subscribe 実装 →GraphQLSchema
- この
GraphQLSchema
にはresolve/subscribe
が含まれる
- この
なので resolve
など実行時用の定義を除けば、これらの表現は相互変換可能、ということになります。
早見表
output \ source | Schema Language | Introspection Result | GraphQLSchema Instance | AST |
---|---|---|---|---|
Schema Language | printSchema |
|||
Introspection Result | (*) | |||
GraphQLSchema Instance | buildSchema , makeExecutableSchema |
buildClientSchema |
buildASTSchema |
|
AST | parse |
(*) graphql(schema, introspectionQuery)
で取得可能
こうしてみると GraphQLSchema
インスタンスへの変換が一番充実していることがわかりますね。直接変換できなくても、例えば
printSchema(buildClientSchema(introspectionResult))
のようにすると Introspection Result から GraphQL Schema Language が得られるように、複数組み合わせれば大体の場合は相互変換ができそうですね。