Build a GraphQL server and Catch ‘Em All !
I created this project https://poke-react.herokuapp.com/ to introduce GraphQL, but progressively he became a test project where I played with technologies like React, Semaphore (Continous Integration), Heroku or yet Docker. I propose to (re)code this Pokédex with me :)
Today we build the server part with GraphQL !
If you don’t know what GraphQL is, see these resources :
- http://graphql.org/learn/
- https://learngraphql.com/
- http://fr.slideshare.net/FabiendeMaestri/lets-graph (My presentation given in Paris Node.js Meetup)
Basic http server :
Let’s make a very basic express server running on port 3001.
npm i --save express
Then we are going to add some GraphQL resource to fetch pokemons from PokéApi.
It’s a REST API totally free to use, but you can donate to support them.
We can fetch for pokemons with this route /pokemon-form. It’s limited at twenty results per page.
We can fetch for a specific Pokemon with an id, example with Butterfree.
Let’s begin by fetch a specific Pokemon. For our Pokédex we need these fields :
- id : String
- name : String
- order : Integer
- img (sprites.front_default) : String
Create a file pokemon.js in folder /schema/pokemon. That will be our pokemon GraphQL type.
We can add an id argument to fetch a particular Pokemon. In the resolve function, we return a mock for now.
Here our pokemon resource :
The Root Schema
The rootSchema contains all types which can be reached in root of a query
Here pokemon can be called directly, but not version because it’s not in root schema.
Create rootSchema.js in shema directory
Express + GraphQL
We want access GraphQL by the endpoint /graphql and pass the query with the query param graphqlQuery .
So with Express we make a GET route, and we test the presence of our query param, else we return a 500.
Then we process the query with GraphQL.
Let’s try our server and install graphql :
npm install —-save graphqlnode index.js
Browse this url. You should see your mock :)
It’s not very easy to interact with a query url, so we are going to add GraphiQL
GraphiQL is an interface to interact with graphQL. You have access to autocompletion, schema introspection, variable interaction with query…
npm install --save express-graphql
Plug with your server on /graphiql endpoint.
Now you can browse http://localhost:3001/graphiql and play with your api.
Type your query, and validate with play button or cmd + enter (mac user)
No more mocks
It’s cool, but mocks are for babies ! We want to connect with the pokéapi.
Create a pokemon.client.js in pokemon folder, and install request-promise to make requests with Promise support. Resolve function in graphQL should always return Promise to not block resolution of other fields.
In graphQL, resources on the same level are resolved in parallel and sub-resource sequentially. For example :
Of course it’s not required for immediate resolution. Like
Promise.resolve(`# ${pokemon.order}`)
We can install request-promise and also bluebird :
npm install --save request
npm install --save request-promise
npm install --save bluebird
We have to expose a method to request the pokéapi with an id. Remember the url was http://pokeapi.co/api/v2/pokemon-form/:id/.
getPokemon takes an id, request the api and return a promise.
Remplace the mock by getPokemon in pokemon.js
Don’t forget to pass an id at you query :)
Catch them all !
Alright, now we want a set of pokemon. In the rootSchema, create a pokemons type. That will be a list of pokemon type, args are not necessary.
If it’s the same type, how can I distinguish pokemon or pokemons ?
In the resolve ! With the presence of an id param.
I use get from lodash. It prevent you to access a child property of undefined parent, very useful.
npm install --save lodash.get
Just add getPokemons to your client, and everything will be ok !
Conclusion
So we have an API, allow us to list pokemons or find a specific one. Next step is to learn how to test GraphQL.
Then we add a front with React :)
See you there !
Source here : https://github.com/zgababa/testpokereact on branch Chapter1
Source final here : https://github.com/zgababa/PokeReact
P.S Sorry for my english, I’m french. Don’t hesitate to correct me in comments :)