An alternative to REST API Endpoints?
This presentation is based heavily off of
GraphQL is both a Query Language for Graph Data and a specification for an API service that will handle GraphQL requests
The goal of GraphQL is to provide an alternate standard to REST APIs for modern web applications, particularly those with a client side focus
You can find a more detailed explanation from Facebook (here and here) but the core weakness of REST that they are addressing is:
"Fetching complicated object graphs require multiple round trips between the client and server to render single views. For mobile applications operating in variable network conditions, these multiple roundtrips are highly undesirable"
Retrieving complex data requires multiple requests from a REST api.
This is bad for mobile.
GraphQL allows you to bundle data requirements for your query so it can be served by one end point
A Query:
{
posts {
title
person {
firstName
lastName
}
}
}A Response:
{
"data": {
"posts": [
{
"title": "Birds are crazy, by Earnest",
"person": {
"firstName": "Earnest",
"lastName": "Crooks"
}
},
{
"title": "Birds are the Best, by Zoey",
"person": {
"firstName": "Zoey",
"lastName": "Bins"
}
},Our "stack":
Things to note:
The real difference is where we would define the routes. Instead of something like:
router.get('/products', function(req, res, next) {
models.product.findAll()
.then(function(products) {
res.render('products', {products:products});
});
});We map the models in Sequelize to the GraphQL schema, and then use a general purpose "query" (or route)
var Post = new ObjectType({
name: 'Post',
description: 'this is a post',
fields: function() {
return {
title: {
type: graphQL.GraphQLString,
resolve(post) {
return post.title;
}
},
content: {
type: graphQL.GraphQLString,
resolve(post) {
return post.content;
}
},
person: {
type: Person,
resolve(post){
return post.getPerson();
}
}
};// end of return
}
});var Query = new ObjectType({
name:'Query',
description:'This is a root query',
fields: function(){
return {
people:{
type: new graphQL.GraphQLList(Person),
args:{ // santize args for security...
id: {
type:graphQL.GraphQLInt
},
email: {
type: graphQL.GraphQLString
}
},
resolve(root,args){ // associate the root query to the db.
console.log('args is ',args);
return db.person.findAll({where:args})
}
},
posts:{
type: new graphQL.GraphQLList(Post),
resolve(root,args){ // associate the root query to the db.
console.log('args is ',args);
return db.post.findAll({where:args})
}
}
}
}
});"Posts" are done via "Mutations" which are predefined functions the client can access:
var Mutation = new ObjectType({
name: 'Mutation',
description: 'this is like a POST',
fields: function(){
return {
addPerson: {
type: Person,
args: {
firstName: {
type: new graphQL.GraphQLNonNull(graphQL.GraphQLString)
},
lastName: {
type: new graphQL.GraphQLNonNull(graphQL.GraphQLString)
},
email: {
type: new graphQL.GraphQLNonNull(graphQL.GraphQLString)
}
},
resolve(_, args){
return db.person.create({
firstName:args.firstName,
lastName:args.lastName,
email:args.email.toLowerCase()
})
}
}
}
}
})Andrew should now bring up
Also postman