Introduction to GraphQL and Hasura

whoami?

Tech Lead at Hasura

 

Twitter: @aleksandrasays

GitHub: @beerose

Blog: aleksandra.codes

Agenda

  1. Introduction to GraphQL
  2. What is Hasura?

Introduction to GraphQL

1. Fetching data

REST API call

App

API

GET api/users
GET api/tasks/user_id=1
{
  users: [
    {
      id: 1,
      name: "Jon",
      surename: "Doe"
    }
  ]
}
GET api/tasks/user_id=1
{
  tasks: [
    {
      name: "Learn GraphQL",
      completed: false,
    }
  ]
}

REST API call

App

API

GET api/users/user_id=1
GET api/tasks/user_id=1
GET api/tasks/user_id=1
GET api/users/details/user_id=1
GET api/tasks/details/task_id=1

Problem: four API calls

REST API call

GET api/users/user_id=1
GET api/tasks/user_id=1
GET api/user_info/user_id=1
GET api/users/details/user_id=1
GET api/tasks/details/task_id=1

Solution: new ednpoints

GET api/tasks_info/user_id=1

REST API call

Problem: different data on different views

example.com/user/1

example.com/users/summary

All users

Profile

pic

User data

More user data

REST API call

Solution: specify fields in API call 

GET api/user_info/user_id=1&fileds=name&fileds=profile_pic

REST API call

Problem: we want only tasks in progress

example.com/tasks/in_progress

Tasks in progress

  • Learn GraphQL

REST API call

Solution: add filter to query parameters

GET api/tasks_info/filter.status=in_progress

GraphQL API call

App

API

query {
  users(id: 1) {
    name
    surename
  }
}
{
  "users": [
    {
      "name": "Jon",
      "surename": "Doe",
    }
  ]
}
query {
  users(id: 1) {
    name
    surename
  }
}

GraphQL API call

App

API

query {
  users(id: 1) {
    name
    surename
    tasks(user_id: 1) {
      name
      status
    }
  }
}
{
  "users": [
    {
      "name": "Jon",
      "surename": "Doe",
      "tasks": [
        {
          "name": "Learn GraphQL",
          "status": "in_progress"
        }
      ]
    }
  ]
}

GraphQL API call

App

API

query {
  users(id: 1) {
    name
    surename
    tasks(user_id: 1, 
     status: "completed") {
      name
      status
    }
  }
}
{
  "users": [
    {
      "name": "Jon",
      "surename": "Doe",
      "tasks": []
    }
  ]
}

Data models are a graph

User 1

Task 1

Task 2

Tag 1

Tag 2

Tag 3

query {
  user(id: 1) {
    ...
    tasks {
      ...
      tags {
       ...
      }
    }
  }
}

You control data you get

User 1

Task 1

Task 2

Tag 1

Tag 2

query {
  user(id: 1) {
    name
    tasks {
      name
      status
      tags {
       id
      }
    }
  }
}

name

surename

age

status

name

priority

name

priority

status

description

id

description

id

Tag 3

description

id

REST API

GraphQL API

API

App

GET users/
GET tasks/
GET tags/

API

App

POST graphql/
Body:
{ "query": "query { users {...} }" }

vs

2. Updating data

REST API

App

API

POST api/users/create

{
  "name": "Jon"
}
Status 200

{
  "id": 1
}

POST

PUT

PATCH

DELETE

GraphQL API

App

API

mutation {
  insertTaks(payload: {...}) {
    id
  }
}
mutation {
  insertTaks(payload: {...}) {
    id
  }
}
Status 200

{
  "id": 1
}

3. Real-time API

App

API

REST API

Option #1

Polling

Option #2

Websockets

App

API

GraphQL API

subscribtion {
  tasks {
    id
    status
  }
}
ws://myapi.com/graphql
"tasks": [
  {
    "id": 1,
    "status": "completed"
  }
]

4. Passing parameters

REST API

GET api/users/user_id=1
let userId = user.id;

get(url, { user_id: userId })

GraphQL API

query {
  users(id: 1) {
    name
    surename
  }
}

string

How can we send arguments programatically?

GraphQL API

query {
  users(id: 1) {
    name
    surename
  }
}

string

How can we send arguments programatically?

const query = `query {
  users(id: ${userId}) {
    name
    surename
  }
}`

post(url, { query })

😕

GraphQL API

query {
  users(id: 1) {
    name
    surename
  }
}

string

How can we send arguments programatically?

const query = `query FetchUser($userId: string) {
  users(id: ${userId}) {
    name
    surename
  }
}`

post(url, { query, variables: { userId: user.id } })

5. API docs

REST API

Option #1

Docs are autogenerated

 

 

👎 Codegen tools are limited

Option #2

Developer manually creates docs

 

 

👎 Easy to get out-of-sync

GraphQL API

Schema is your documentation

User 1

Task 1

Task 2

Tag 1

Tag 2

name

surename

age

status

name

priority

name

priority

status

description

id

description

id

Tag 3

description

id

type User {
  id: Int!
  name: String!
  surname: String
  age: Int
}

type Task {
  id: Int!
  name: String!
  status: String
  priority: Number
}

type Tag {
  id: String!
  description: String
}

GraphQL API

Introspection API

{ 
  __type(name: "users") {
    name
    fields {
      name
      type {
        name
        kind
        inputFields {
          name
        }
      }
    }
  }
}
{
  "data": {
    "__type": {
      "name": "users",
      "fields": [
        {
          "name": "id",
          "type": {
            "name": "String",
            "inputFields": null,
            "kind": "SCALAR"
          },
        },
        {
          "name": "name",
          "type": {
            "name": "String",
            "inputFields": null,
            "kind": "NON_NULL"
          },
        },
        {
          "name": "created_at",
          "type": {
            "inputFields": null,
            "kind": "NON_NULL"
          },
          "description": null
        },
    }
}

Introduction to GraphQL summary

GET

POST

PUT

PATCH

DELETE

query

GET

GET

mutation

subscription

Introduction to Hasura

What is Hasura?

Open source • GraphQL engine

 

Realtime GraphQL Engine

 

GraphQL Queries Compiler

 

users {
  name
  posts {
    title
    content
    tags {
      name
    }
  }
}
SELECT 
  users.name
  posts.title
  posts.content
  tags.name
FROM 
  users, posts, tags
WHERE
  users.id = posts.author_id,
  posts.id = tags.post_id

Authorization

 

 

Authentication

Webhook mode

App

Query
req headers

 

</>
variables
eg. x-hasura-user-id
req headers

 

Webhook

Authentication

JWT mode

App

Auth

Service

JWT
Hasura claims
Query, JWT

 

App

Remote Schemas

 

Unified GraphQL API

GraphQL Service

Data Triggers

APIs

Background jobs

GraphQL mutations

Event queue

Microservices

Serverless functions

Cron Triggers

Event queue

Microservices

Serverless functions

One-off Scheduled Triggers

Event queue

Microservices

Serverless functions

Actions

App

</>
GraphQL 
query / mutation

POST endpoint

Actions

Multiple databases

App

  • Postgres
  • Yugabyte
  • Timescale
  • MS Server
  • Big Query

Hasura Cloud

Takeaways