Presented by @jayhogan
Application Development Lead, SingleStone Consulting
A query language for your API
A type system to describe your data
A server-side runtime to execute queries
GET http://myapi.io/author/2
HTTP/1.1 200 OK
{
"first_name":"Douglas",
"last_name":"Crockford"
}
GET http://myapi.io/author/2/books
HTTP/1.1 200 OK
[{
"id":3,
"name":"Javascript: The Good Parts",
"isbn":"0596517742",
"publish_date":"2016-05-31"
}]
GET http://myapi.io/books
# For each book - yikes!
GET http://myapi.io/book/1
GET http://myapi.io/book/1/ratings
GET http://myapi.io/author/2
GET http://myapi.io/author/2/books
GET http://myapi.io/book/3?view=full
{
"id":3,
"name":"Javascript: The Good Parts",
"isbn":"0596517742",
"publish_date":"2016-05-31",
"author": {
"first_name":"Douglas",
"last_name":"Crockford"
}
}
GET http://myapi.io/book/3?view=compact
{
"id":3,
"name":"Javascript: The Good Parts"
}
GET http://myapi.io/book/A
HTTP/1.1 500
Unexpected error
POST http://myapi.io/book/1
{"foo":"bar"}
HTTP/1.1 500
Unexpected error
"REST is intended for long-lived network-based applications that span multiple organizations." -- Roy Fielding
"What needs to be done to make the REST architectural style clear on the notion that hypertext is a constraint?" -- Roy Fielding
GET http://myapi.io/book
GET http://myapi.io/bookComparison
GET http://myapi.io/bookSnippet
GET http://myapi.io/bookMobile
Product Owner: Can I add the book publication date to the page?
Developer: That's a 3 point story.
Product Owner: But it's just a simple date!
{
books {
name
author {
first_name
last_name
}
publish_date
}
}
"books": [
{
"name": "JavaScript: The Definitive Guide",
"author": {
"first_name": "David",
"last_name": "Flanagan"
},
"publish_date": "2011-05-13"
},
{
"name": "JavaScript: Pocket Reference",
"author": {
"first_name": "David",
"last_name": "Flanagan"
},
"publish_date": "2012-04-28"
}]
{
books {
name
price(currency: USD)
}
}
"books": [
{
"name": "JavaScript: The Definitive Guide",
"price": 32.64
},
{
"name": "JavaScript: Pocket Reference",
"price": 13.47
}]
{
books {
name
price(currency: USD)
euPrice: price(currency: EUR)
}
}
"books": [
{
"name": "JavaScript: The Definitive Guide",
"price": 32.64,
"euPrice": 28.0704
},
{
"name": "JavaScript: Pocket Reference",
"price": 13.47,
"euPrice": 11.584200000000001
}]
{
books {
name
price(currency: $currency)
}
}
# Variables
{
currency: "USD"
}
"books": [
{
"name": "JavaScript: The Definitive Guide",
"price": 32.64
},
{
"name": "JavaScript: Pocket Reference",
"price": 13.47
}]
mutation AddRating($rating: RatingInput!) {
addRating(rating: $rating) {
id
rating
date
}
}
# Variables
{
rating {
book_id: 1, user_id: 1, rating: 5
}
}
"addRating": {
"id": 15,
"rating": 5,
"date": "2017-11-01"
}
But there is no more time...sorry. ¯\_(ツ)_/¯
type Book {
id: Int
name: String
isbn: String
}
type ScalarGrabBag {
id: ID
string: String
float: Float
int: Int
bool: Boolean
}
type Book {
id: Int
name: String
isbn: String
author: Author
}
type Author {
first_name: String
last_name: String
}
type Book {
id: Int! # id will never be null
name: String
isbn: String
author: Author!
ratings: [Rating] # ratings is a list/array
}
enum Currency {
USD
CAD
EUR
}
type Book {
id: Int!
name: String
isbn: String
price(currency: Currency = USD): Float!
}
type Query {
books: [Book]
authors: [Author]
users: [User]
search(name: String): [SearchResult]
}
type Mutation {
addRating(rating: RatingInput!): Rating
}
But there is no more time...sorry. ¯\_(ツ)_/¯
Server-side validation and execution of graphql queries
API developers leverage GraphQL server libraries
Use the library to build the type system and field resolvers
Comes for free with compliant GraphQL server libraries
{
books { () => repo.books() # returns array of books
# for each book
name (book) => book.name
author { (book) => repo.findAuthor(book) # returns author object
first_name (author) => author.first_name
}
}
}
{
books {
name
author {
first_name
last_name
bio
books { name }
}
ratings { rating }
}
}
{ "books": [
{
"name": "JavaScript: The...",
"author": {
"first_name": "David",
"last_name": "Flanagan",
"bio": "David Flanagan is a computer programmer who..."
"books": [
{ "name": "JavaScript: T..." }
]
},
"ratings": [
{ "rating": 3 }
]
}
]}
{
books {
name
isbn
author {
first_name
last_name
books { name }
}
price(currency: USD)
}
}
{
books {
name
author {
last_name
}
}
}
{
books {
name
author { firstName }
}
}
# Response
{
error: "Cannot find field 'firstName' on 'Author'. Did you mean 'first_name'?"
}
Designed for building client-focused, product-based APIs
Now there is one endpoint: /graphql
Not with GraphQL
{
books {
name
author { firstName }
publish_date
}
}
{
books {
name
author {
books {
author {
books {
author {
last_name
}
}
}
}
}
}
}
{
books {
name
author { # Resolver is called for each book
books { # Resolver is called for each book, author
name
}
}
}
}
singlestone/graphql-rescue » GraphQL » Docs » Community Resources » GraphQL Spec » Explore GraphQL » Fullstack Tutorial