API Driven Development with

GraphQL

tjwebb@langa.io


github.com/tjwebb

Part 1

- What is GraphQL

- The Language

- The Runtime

Part 2
- GraphQL Use Cases

What is GraphQL?

"GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data."

 

-- graphql.org

What is GraphQL?

"All the things that make SOAP awesome minus all the things that make SOAP terrible"

 

-- tjwebb

SOAP WSDL

<?xml version="1.0"?>
<definitions name="StockQuote"
          targetNamespace="http://example.com/stockquote.wsdl"
          xmlns:tns="http://example.com/stockquote.wsdl"
          xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"
          xmlns:xsd1="http://example.com/stockquote.xsd"
          xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
          xmlns="http://schemas.xmlsoap.org/wsdl/">
    <message name="GetTradePriceInput">
        <part name="tickerSymbol" element="xsd:string"/>
        <part name="time" element="xsd:timeInstant"/>
    </message>
    <message name="GetTradePriceOutput">
        <part name="result" type="xsd:float"/>
    </message>
    <portType name="StockQuotePortType">
        <operation name="GetTradePrice">
           <input message="tns:GetTradePriceInput"/>
           <output message="tns:GetTradePriceOutput"/>
        </operation>
    </portType>
    <binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="GetTradePrice">
           <soap:operation soapAction="http://example.com/GetTradePrice"/>
           <input>
               <soap:body use="encoded" namespace="http://example.com/stockquote"
                          encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
           </input>
           <output>
               <soap:body use="encoded" namespace="http://example.com/stockquote"
                          encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
           </output>
        </operation>>
    </binding>
    <service name="StockQuoteService">
        <documentation>My first service</documentation>
        <port name="StockQuotePort" binding="tns:StockQuoteBinding">
           <soap:address location="http://example.com/stockquote"/>
        </port>
    </service>
</definitions>

SOAP !!

What is GraphQL?

Imagine a service endpoint that accepts a query ...

POST /sql

select
  name,
  email,
  cats
from user
where cats >= 5

What is GraphQL?

... disallows bad things ... 

What is GraphQL?

... returns exactly the response shape you ask for ...

[
  {
    "name": "tjwebb",
    "email": "tjwebb@langa.io",
    "cats": 5
  }
]

What is GraphQL?

... enforces types, is

self-documenting ...

type User {
  name: String!
  email: String!
  cats: Int!
  kats: Int @deprecated
}

What is GraphQL?

... declarative ...

query {
  catUsers: user(cats: 5) {
    name
    cats
  }
  normalUsers: user(cats: 0) {
    name
    cats
  }
}
{
  "catUsers": [
    {
      "name": "tjwebb",
      "cats": 5
    }
  ],
  "normalUsers": [ ]
}

What is GraphQL?

... has a surprisingly-readable

specification with examples ...

 

 

 

facebook.github.io/graphql

What is GraphQL?

... and built by people who know what the hell they're doing.

REST Request

GET /user?name=tjwebb
{
  "user": {
    "name": "tjwebb",
    "email": "tjwebb@langa.io"
  }
}

REST Request

GET /user?name=tjwebb
{
  "user": {
    "omg": "lol",
    "password": "hunter2"
  }
}

REST Request

GraphQL Request

POST /graphql
user (id: 1) {
  name
  email
}
{
  "user": {
    "name": "tjwebb",
    "email": "tjwebb@langa.io"
  }
}

REST Middleware

GET /user?name=tjwebb&fields=email,cats

handler (request, reply) {
  const query = request.query
  // validate query parameters

  knex('user')
    .where({ name: query.name })
    .select(query.fields.split(','))
    .then(result => {
      // ... sanitize/validate result
      reply(result)
    })
}

REST Middleware

1. Parse/validate arguments

2. Get data

3. Transform/validate results

4. Return to client

GraphQL Middleware

POST /graphql

handler (request, reply) {
  reply(graphql(this.schema, request.payload))
}

GraphQL Middleware

1. Define GraphQL Schema

2. Implement Resolvers

What is GraphQL?

"GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data."

 

-- graphql.org

GraphQL Schema


type UserQuery (email: String, cats: Int) {
  name: String
  email: String
  cats: Int
}

schema {
  query: {
    user: UserQuery
  }
}

GraphQL Query


type UserQuery (email: String, cats: Int) {
  name: String
  email: String
  cats: Int
}

schema {
  query: {
    user: UserQuery
  }
}

GraphQL Resolvers

type UserQuery (email: String, cats: Int) {
  name: String
  email: String
  cats: Int
}

class User {
  static resolver ({ email, cats }) {
    return knex('user').where({ email, cats })
      .then(([ record ]) => new User(record))
  }
}

GraphQL Resolvers

type UserQuery (email: String, cats: Int) {
  ...
  dynamicField: Float
}
class User {
  static resolver ({ email, cats }) {
    return knex('user').where({ email, cats })
      .then(([ record ]) => new User(record))
  }

  get dynamicField () {
    return Math.random()
  }
}

GraphiQL.io

GraphQL Use Cases

Obvious Ideas

- Use it for your Startup Idea

 

- Pub/sub Twitter Bot

 

- Wrap an existing REST API

 

- Node.js ORM

Obvious Ideas

Use Cases

Mainframe Integration

Mainframe Integration

COBOL

Mainframe Integration

ESB Integration

ESB Integration

GraphQL Users

- Facebook

- Github

- Twitter

- Intuit

- Financial Times

- Shopify

- Wayfair

- Coursera

Questions?

tjwebb@langa.io


github.com/tjwebb

 

@tjwebbOnGithub

Made with Slides.com