GraphQL Mesh とは
The Guildから GraphQL Meshが発表されました。
🚀 GraphQL Mesh - Query Anything, Run Anywhere 🚀https://t.co/PlZpAC9b54
— Urigo (@UriGoldshtein) March 23, 2020
🎉 I'm very proud to announce our new open source library - GraphQL Mesh!
Use #GraphQL to query:
🔹 openapi/Swagger
🔹 gRPC
🔹 SOAP
🔹 SQL
🔹 GraphQL
🔹 More!
Without changing the source!
Thread 1/5 pic.twitter.com/xo0G5smUwp
GraphQL Mesh は REST API や gRPC などの既存のバックエンド API サービスと接続するプロキシとして機能します。
GraphQL Mesh は、開発者が他の API 仕様(gRPC、OpenAPI、Swagger、oData、SOAP、GraphQL など)で記述されたサービスに対して、GraphQL のクエリを通じて簡単にアクセス可能にすることを目的として作られました。
従来、GraphQL プロキシを実装するためには、バックエンド API サービスに対して以下の作業を行う必要がありました。
- その API 仕様を読み解き、
- GraphQL サーバを構築し、
- スキーマ、リゾルバ、バックエンド API との通信処理を実装する
複数のバックエンド API をラップする GraphQL サーバを実装するためだけに多大な労力を割いていたのです。
もちろん、openapi-to-graphqlのように、OpenAPI 定義を GraphQL のスキーマに読み換えるツールや、スキーマ定義からモックサーバを構築する graphql-toolsなどは登場していました。
今回登場した GraphQL Mesh は革新的です。バックエンド API の API 仕様さえあれば、そのバックエンド API に対して GraphQL クエリが即座に実行できる GraphQL プロキシが手に入ります。
本記事では GraphQL Mesh の簡単な使用方法とアーキテクチャの構成パターンについて解説します。
※ 本記事は こちらの記事を参照しています。
使用方法
バックエンドに OpenAPI で記述された REST API サービスがあることを想定して、GraphQL Mesh によるプロキシサーバを構築します。今回バックエンドの API は Qiita APIを使用します。
1. インストール
GraphQL Mesh はいくつかのコアライブラリを組み合わせてインストールします。
$ yarn add graphql \
@graphql-mesh/runtime \
@graphql-mesh/cli \
@graphql-mesh/openapi
使用可能な API(と実装予定の API)は 3/25 現在、以下の通りです。
| Package | Status | Supported Spec |
|---|---|---|
@graphql-mesh/graphql | Available | GraphQL endpoint (schema-stitching, based on graphql-tools-fork) |
@graphql-mesh/federation | WIP | Apollo Federation services |
@graphql-mesh/openapi | Available | Swagger, OpenAPI 2/3 (based on openapi-to-graphql) |
@graphql-mesh/json-schema | Available | JSON schema structure for request/response |
@graphql-mesh/postgraphile | Available | Postgres database schema |
@graphql-mesh/grpc | Available | gRPC and protobuf schemas |
@graphql-mesh/soap | Available | SOAP specification |
@graphql-mesh/mongoose | Available | Mongoose schema wrapper based on graphql-compose-mongoose |
@graphql-mesh/odata | WIP | OData specification |
2. 設定ファイルにバックエンド API の API 仕様を記述する
次に、.meshrc.yamlというファイルを作成し、バックエンド API の API 仕様を記述しましょう。今回は OpenAPI を使用します。他にも gRPC、oData、SOAP、GraphQL などをサポートしています。.meshrc.yamlはプロジェクトのルートディレクトリに配置します。
sources:-name:Qiitahandler:openapi:source:./qiita.openapi.yamlQiitaAPI の OpenAPI 定義 .qiita.openapi.yamlは以下のように記述しています。
Qiita APIの仕様 (OpenAPI)
swagger:"2.0"info:version:0.0.1title:Qiita APIhost:"qiita.com"basePath:"/api/v2"schemes:-httpsconsumes:-application/jsonproduces:-application/jsonpaths:"/tags/{tagId}/items":get:parameters:-in:pathname:tagIdtype:stringrequired:true-$ref:"#/parameters/pageParam"-$ref:"#/parameters/perPageParam"responses:"200":description:指定されたタグが付けられた投稿一覧を、タグを付けた日時の降順で返します。schema:title:タグ記事一覧type:arrayitems:$ref:"#/definitions/Item""/users/{userId}":get:parameters:-in:pathname:userIdtype:stringrequired:trueresponses:"200":description:ユーザを取得します。schema:$ref:"#/definitions/User""/users/{userId}/items":get:parameters:-in:pathname:userIdtype:stringrequired:true-$ref:"#/parameters/pageParam"-$ref:"#/parameters/perPageParam"responses:"200":description:ユーザの投稿の一覧を作成日時の降順で返します。schema:title:ユーザー記事一覧type:arrayitems:$ref:"#/definitions/Item""/items":get:parameters:-$ref:"#/parameters/pageParam"-$ref:"#/parameters/perPageParam"-name:queryin:querydescription:検索クエリrequired:falsetype:stringresponses:"200":description:投稿の一覧を作成日時の降順で返します。schema:title:記事一覧type:arrayitems:$ref:"#/definitions/Item"parameters:pageParam:in:queryname:pagedescription:ページ番号 (1から100まで)type:numberperPageParam:in:queryname:per_pagedescription:1ページあたりに含まれる要素数 (1から100まで)type:numberdefinitions:ErrorMessage:description:エラーの内容を説明するmessageプロパティと、エラーの種類を表すtypeプロパティで構成されますtype:objectproperties:message:type:stringtype:type:stringGroup:description:"Qiita:Teamのグループを表します。"type:objectproperties:created_at:type:stringid:type:integername:type:stringprivate:type:booleanupdated_at:type:stringurl_name:type:stringTag:description:タグproperties:name:type:stringexample:Rubyversions:type:arrayitems:type:stringexample:0.0.1User:properties:description:description:自己紹介文type:stringfacebook_id:type:stringfollowees_count:description:このユーザがフォローしているユーザの数type:integerfollowers_count:description:このユーザをフォローしているユーザの数type:integergithub_login_name:type:stringid:type:stringitems_count:description:"このユーザがqiita.com上で公開している投稿の数(Qiita:Teamでの投稿数は含まれません)"type:integerlinkedin_id:type:stringlocation:type:stringname:type:stringorganization:type:stringpermanent_id:description:ユーザごとに割り当てられる整数のIDtype:integerprofile_image_url:description:設定しているプロフィール画像のURLtype:stringtwitter_screen_name:type:stringwebsite_url:type:stringItem:type:objectproperties:rendered_body:type:stringbody:type:stringcoediting:type:booleancomments_count:type:integercreated_at:type:stringid:type:stringlikes_count:type:stringprivate:type:booleanreactions_count:type:integertitle:type:stringupdated_at:type:stringurl:type:stringpage_views_count:type:integertags:type:arrayitems:$ref:"#/definitions/Tag"user:$ref:"#/definitions/User"group:$ref:"#/definitions/Group"
3. GraphQL Mesh サーバを起動する
GraphQL Mesh サーバを起動します。以下コマンドは npm scriptsに設定しておくと良いでしょう。
$ yarn graphql-mesh serve
yarn run v1.22.4
info: 🕸️ => Serving GraphQL Mesh GraphiQL: http://localhost:4000/
http://localhost:4000/で GrapiQLが起動します。ブラウザを開いて確認しましょう。
4. GraphQL クエリを実行する
Qiita 記事の情報と、記事に紐づくユーザ情報も合わせて取得します。複数の REST API で取得できる情報をネストして記述し、1回のクエリで取得できることこそが GraphQL の真骨頂です。
query getItems {
getItems{
title
likesCount
user {
name
itemsCount
organization
description
}
}
}
きちんと取得できているようです。
さらに OpenAPI のモデルの定義を正確に読み解き、GraphQL のスキーマ定義にもきちんと反映ができています。素晴らしい。
GraphQL Mesh の活用方法
GraphQL Mesh はバックエンド API のプロキシとして機能します。この性質から、クライアントに対する GATEWAY としてふるまい、複数のバックエンドを束ねた構成をとっても良いでしょう。
また、複数のマイクロサービスが内部で相互通信する際に、HUB とする構成を取ることもできます。
まだ開発初期段階らしく、GitHub の README には以下のように記されています。
Note: this project is early and there will be breaking changes along the way
今後大きく変更されることがあるかもしれません。ただ、このツールのコアコンセプトには非常に感銘を受けます。AWS の AppSync などの GraphQL マネージドサービス系がこの考え方を取り入れたら、Web API の業界に大きなインパクトがありそうだと感じました。





