BUILDING

production-ready

GraphQL

APIS

Ben Wilson

Bruce Williams

AGENDA

Agenda: day 1

08:30 10:00 Intro, GraphQL Basics, App Setup
10:00 10:30 Break
10:30 12:00 Core Types & Modeling
12:00 01:30 Lunch
01:30 03:00 Subscriptions & Auth
03:00 03:30 Break
03:30 05:00 Complex Modeling & Batching

Bruce williams

Twitter: @wbruce

GitHub: @bruce

Elixir Forum: @bruce

Elixir Slack: Bruce Williams

BEN WILSON

Twitter: @benwilson512

GitHub: @benwilson512

Elixir Forum: @benwilson512

Elixir Slack: benwilson512

industry 1

INDUSTRY 2

INDUSTRY 3

EST. Oct 2015

v1.4

Absinthe

v1.5

NEXT:

pipeline-based schema definition system

NEW LEXER

schema stitching

graphql SDL support

more flexible imports

elixir graphql client

ALPHA (to be released  following ElixirConf)

BETA

PERFORMANCE improvements

GraphQL

Basics

Graph

Query

Language

data query language

compare to: sql

query {
  post(id: "abc-123") {
    title
    publishedDate
    author {
      name
    }
    body
  }
}
{
  "data": {
    "post": {
      "title": "ElixirConf 2018",
      "publishedDate": "2018-09-04",
      "author": {
        "name": "Bruce Williams"
      },
      "body": "..."
    }
  }
}

you get what you ask for

http api

compare to: rest

query ($userId: ID!, $since: Date) {
  user(id: $userId) {
    posts(since: $since) {
      title
      publishDate
    }
  }
}
{"userId":"12", "since":"2018-01-01"}
{
  "data": {
    "user": {
      "posts":[
        {"title": "Example1", "publishDate":"2018-01-01"},
        {"title": "Example2", "publishDate":"2018-01-02"}
      ]
    }
  }
}

GraphQL

variables

result

it's not just about queries

query

Subscribes to an event,

requests information be

sent later (over WS, etc)

query ($search: String, $limit: Int = 10) {
  posts(matching: $search, limit: $limit) {
    title
    author { name }
  }
}

mutation

Requests information.

mutation ($postContent: PostInput!) {
  createPost(input: $postContent) {
    assignedEditor { name }
    publicationStatus
  }
}
subscription ($postId: ID!) {
  reviewCompleted(postId: $postId) {
    editor { name }
    requestedChanges {
      changeType
      notes
    }
  }
}

Modifies data, requests

information in response.

subscription

GraphQL Operations

websocket!

how it works

schema

a graph of relationships between types

Post

Comment

User

posts

author

comments

subject

String

Date

name

birthdate

Object types

, fields

, and extensible scalar types

... plus enumerations, unions, interfaces, and others

Defining a GraphQL Schema

Post

User

posts

Defining a GraphQL Schema

Fields define relationships between types

name

String

author

Post

User

posts

Query

Root

posts

post

user

users

Root object types are entry points for GraphQL operations

Defining a GraphQL Schema

graphql document

describes a TREE to EXTRACT FROM a schema graph

a graphQL query narrative

query {
  posts(matching: "conference", limit: 10) {
    title
    author { name }
    comments(limit: 3, order: {by: VOTES, direction: DESC}) {
      body
    }
  }
}

This is a query operation, resolve the root query value.

Resolve its posts field, given the provided matching and limit arguments. Expect a list of values we can treat as Post object typed as the result.

For each Post typed value...

a graphQL query narrative

query {
  posts(matching: "conference", limit: 10) {
    title
    author { name }
    comments(limit: 3, order: {by: VOTES, direction: DESC}) {
      body
    }
  }
}

Resolve its title field. Expect a value that we can handle as a String scalar type as the result. Save it.

Resolve the post's author field. Expect a value we can treat as a User object type as the result.

With that User value...

a graphQL query narrative

query {
  posts(matching: "conference", limit: 10) {
    title
    author { name }
    comments(limit: 3, order: {by: VOTES, direction: DESC}) {
      body
    }
  }
}

Resolve the name field. Expect a value that we can treat as a String scalar type as the result. Save it.

No more fields for the User typed value. Go back up a level to the last Post typed value.

Resolve its comments field, given the provided input values for the limit and order arguments. Expect a list of values we can treat as Comment typed as the result.

a graphQL query narrative

query {
  posts(matching: "conference", limit: 10) {
    title
    author { name }
    comments(limit: 3, order: {by: VOTES, direction: DESC}) {
      body
    }
  }
}

Resolve the body field. Expect a value we can treat as a String scalar type as the result. Save it.

No more fields for the Comment typed value, go back up a level to the last Post typed value.

For each Comment typed value...

No more fields for the Post typed value, go back up a level to the root query type value.

a graphQL query narrative

query {
  posts(matching: "conference", limit: 10) {
    title
    author { name }
    comments(limit: 3, order: {by: VOTES, direction: DESC}) {
      body
    }
  }
}

No more fields for the root query type value, collect the saved data and return it as a tree data structure.

introspection

tools

project: PASTEx

A GraphQL-driven Elixir pastebin

https://github.com/bruce/pastex

let's

get

started

Building Production-Ready GraphQL APIs (Day 1)

By wbruce

Building Production-Ready GraphQL APIs (Day 1)

ElixirConf 2018 Training Intro, Day 1

  • 936