GraphQL Join or how to find all bars around GraphQL Summit with a single query
If you visited a couple of developer conferences you should know that the most fun part is not the talks but the bar crawl after the event.
So how to find all the bars near GraphQL Summit location? A quick and simple answer would be to just copy the address from official website and paste it into Yelp or FourSquare.
But you don’t need to be a GraphQL guru to do that. How about using GraphQL for getting this data?
We will do this using the following master plan:
- Get the address of venue. Fortunately, Universe recently released GraphQL API for their catalog of events:
2) Find all bars around this venue. No surprise, here we will just use Yelp’s GraphQL API:
Bingo! Problem is solved we get all the necessary data exclusively from GraphQL APIs. But can we reduce it to a single query? What if we could just join two GraphQL APIs together?
Joining GraphQL APIs is a hot topic at the moment and most likely you have already heard about schema stitching concept presented by Apollo. We really like the idea but the complexity of code you have to write looks a bit scary. So we decided to build a new tool from scratch with the idea to join APIs using familiar GraphQL syntax (queries, fragments, IDL) in declarative fashion — GraphQL Join.
GraphQL Join requires some polishing before the public release but we would like to get feedback about our declarative syntax before. So let’s get familiar with it by stitching Universe and Yelp APIs together in exactly 40 lines:
Configuration
Everything can be configured inside a single YAML file which has three top level properties apis
, joinIDL
and transformModule
. Let’s describe them one by one:
apis
: Specify APIs to join and how the can be accessed
GraphQL Join sends introspection query to each of those APIs server to allow reusing remote types in resulting API. We also added support for prefixing types to avoid name clashes if needed (see prefix
property). It’s a good idea to prefix types of API you don’t have control over, e.g. we add prefix Yelp_
to all types from Yelp.
To store access tokens outside of config files and provide them through environment variables we support special construct: ${env: VARIABLE_NAME}
2) joinIDL
: Describe how to merge two APIs together:
Does it look familiar? Yes, we used mixture of standard GraphQL IDL, Query syntax and @export
directive (used by Facebook for batching). The only new things we’ve added are @resolveWith
and @send
directives.
But let’s go step by step.
Here we decide what will be the root type of our joined API. And we specify Query
which is non-prefixed Query
type from Universe API (if we wanted to to do the same with Yelp, we should have used Yelp_Query
).
This will effectively copy all the Universe API. Next, let’s extend it with the data from Yelp:
Here we are adding placesNearby
field into Event
type. Note that the field return type is Yelp_Businesses
.
New field is resolved by sending getPlacesNearby
query to Yelp API with extra arguments provided by LocationForYelp
fragment:
3) transformModule
: Transform arguments. One strange thing you’ve probably noticed is that LocationForYelp
exports address
and cityName
variables but getPlacesNearby
query expects those two as a single location
argument. Sadly we can’t use our declarative syntax for this transformation and need to write a few lines of JS:
You can see whole join.yaml
and join.js
files here and start your new join API with a single command:graphql-join ./universe_yelp/join.yaml
Try it out
Let’s test the resulting API with a query I promised you in the title:
You can play with this API yourself: http://universe-yelp.apis.guru/
Features
Here is the list of what features are already implemented in GraphQL Join:
- Full support of GraphQL queries: aliases, fragments, query variables, etc.
- All request against GraphQL APIs are batched and no special support from your GraphQL server is required.
- Our proxy is absolutely transparent both for the client and the original server. You can even use new joined API to join it with any other API.
What’s next
For the public release we want to ship it together with a slick UI for creating configuration with blackjack and autocompletion 😀.
Our main goal is to define declarative syntax for joining GraphQL APIs which is easy to read and has smooth learning curve. Would be great to get your feedback in comments or in person during GraphQL Summit!