So you have heard about GraphQL! Awesome stuff isn't it, I like it too :). If you are completely new to GraphQL and are looking for a nice way to learn GraphQL that goes a little further then just 'Hello World' then you have come to the right place :). Please do note that this workshop revolves completely around the server side implementation. Client side usage of GraphQL API's might be something to create later in a separate workshop.
Please note that this is an evolving (and a working in progress) tutorial and might grow in content over time.
This project might be in a stage where you are now, you have created a nice REST API and are thinking about possibly expanding it with a GraphQL endpoint as well. As we are mostly concerned about the GraphQL implementation the REST API is provided for you to create the assignments on.
The prerequisites for this workshop are:
- Basic Javascript knowledge
- Basic NodeJS / NPM knowledge
Let's start with a quick overview of our application.
The core frameworks we use to build our REST API are:
- Express is used as our web framework of choice
- Winston is used as our logging framework
- RequestJS to call our external service
- PokeAPI is used as our endpoint to retrieve our data
To test and develop our application we a few frameworks to make everything easier and better to maintain:
- MochaJS as our core testing framework
- SuperTest for HTTP assertions
- Nock to mock (and record) our responses
- Istanbul to get some nice code coverage too
- Nodemon to instantly reload the application on code changes
- EsLint to lint our code
Here are some pre-made scripts that can be used right away:
Start the application (available under http://localhost:3000/api/pokemon if using default configuration)
$ npm start
Start the application in development mode (by default with mocked responses)
$ npm run development
Run all the tests (in with mocked responses)
$ npm test
Run all tests against the real endpoint and record all responses
$ npm run test-and-record
Lint our code
npm run lint
It is quite a complete sample application, however the functionality that it contains is rather basic for but we will start to extend it with the assignments below. However before we go straight into the assignments let's first start with some GraphQL resources. There are quite a few great resources that you can use to gain some basic knowledge on what GraphQL is and how to start implementing it. Here are just a few that you should start with in my opinion:
- GraphQL's own documentation is really good! Should be your first resource to visit :).
- Apollo GraphQL Server as this is the implementation that we will be using for our application
- Introduction Video a great way to get introduced to GraphQL
- GraphQL at Facebook something to watch if you think GraphQL is not ready for production use :)
Not much to add here :) before we continue first read up on the basics with the provided links which should not take you more then an hour. However if you like the practical approach more (like me) just skip on to the next assignment :).
Clone this repo, create your own working branch (or just fork this repo instead) and start by installing all the required dependencies that you will need for this project.
$ npm install body-parser graphql graphql-server-express graphql-tools --save
Create a schema for your GraphQL API using GraphQL tools as documented here. Let's initially start with just listing our pokemon, so create a Schema that should be able to parse the GraphQL query below:
query listPokemon {
pokemon {
id
name
}
}
Create a resolver for your schema to resolve the pokemon from the endpoint. Use the documentation here to setup your resolver and link it to your schema. Don't forget that you can reuse the pokemon client to perform the interaction with the endpoint.
Configure a new express router and configure Apollo's GraphQL server on this route as documented here.
Your GraphQL endpoint should be configured on /api/pokemon/graphql.
Make sure that you also enable GraphiQL in the server as we will be using this AMAZING utility to manually test our GraphQL API.
GraphiQL should be made available on /api/pokemon/graphql/graphiql.
You should have your GraphQL endpoint up and running at this stage! Test it by playing with GraphiQL.
Expand your GraphQL API, this time we want to be able to retrieve details on a pokemon with the query below.
# Example basic query
query getPokemon {
pokemon(id: 1) {
id
name
stats {
name
}
}
}
Adjust your schema and resolvers accordingly.
Create a new test suite, testing your GraphQL API.
Mock your entire GraphQL API as described here. Add a new npm script start-mock that starts up with a new environment variable MOCK_GRAPHQL. If this variable is set to true the GraphQL API should be using mocked values. As a bonus write your own mock generators to generate real pokemon names.
Add a way to retrieve favorite pokemon (sorted by number of votes) and a way to vote for your favorite pokemon. Read more about mutations here.
The schema should be updated to be able to retrieve the favorites count on a specific pokemon as well as add a mutation to update the favorites count:
The following query should retrieve the favCount of pokemon 1.
query listPokemon {
pokemon(id: 1){
id
name
favCount
}
}
The following mutation should increment the favCount of pokemon 1 by 1.
mutation incrementCounter {
incrementFavorite(id: 1) {
id
}
}
TODO Add more steps (subscriptions/dataloader/etc)