Introduction to GraphQL and Hasura

whoami?

Software Engineer at Hasura

 

Twitter: @aleksandrasays

GitHub: @beerose

Blog: aleksandra.codes

Agenda

  1. Introduction to GraphQL
  2. What is Hasura?
  3. Demo and live coding

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
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
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 inside in the query 

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/tasks/

{
  "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. API docs

REST API

Option #1

Docs are autogenerated

 

 

👎 Codegen tools are limited

Option #2

Developer manually create 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
}

Introduction to GraphQL summary

GET

POST

PUT

PATCH

DELETE

query

GET

GET

mutation

subscription

Introduction to Hasura

What is Hasura?

Open source • GraphQL engine • On Postgres

 

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

 

 

App

Remote Schemas

 

Unified GraphQL API

GraphQL Service

Event triggers

APIs

Background jobs

GraphQL mutations

Event queue

Microservices

Serverless functions

Actions

App

</>

Hasura in React application

Apollo

UI

GraphQL query

Fetching data

Sends data

Updates UI

Client processes data

Client normalises and stores data

Demo 🙇‍♀️🙇‍♂️

Setup

1. Install dependencies

yarn add apollo-client @apollo/react-hooks apollo-link-http \
         graphql graphql-tag apollo-cache-inmemory

Setup

2. Create Apollo Client

import ApolloClient from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory";
import { HttpLink } from "apollo-link-http";

export const createApolloClient = () => {
  return new ApolloClient({
    link: new HttpLink({
      uri: "https://<YOUR_GRAPHQL_SERVICE>/graphql",
    }),
    cache: new InMemoryCache(),
  });
};

Setup

3. Add ApolloProvider

import { ApolloProvider } from "@apollo/react-hooks";

const App = () => {
  const client = createApolloClient();

  return (
    <ApolloProvider client={client}>
     {...}
    </ApolloProvider>
  )
}

Setup

4. TypeScript codegen

yarn add @graphql-codegen/cli @graphql-codegen/introspection \
  @graphql-codegen/typescript @graphql-codegen/typescript-operations \ 
    @graphql-codegen/typescript-react-apollo

Resources