GraphQL Workshop

Eve Porcello

@eveporcello

eve@moonhighway.com

Agenda

- Unions / Interfaces

- Fragments

- Understanding Schemas

- Caching / Performance

- Errors

- Q+A

Timing

- 11:00 - Start

- 12:00 - 12:05 - Break

- 1:00 - End

enum PetCategory

DOG

CAT

STINGRAY

RABBIT

type Pet

id: ID!

name: String!

category: PetCategory!

        ...

HORSE

sleepAmount: Int

curious: Boolean

favoriteFood: String

floppy: Int

good: Boolean

chill: Boolean

fast: Boolean

streetsmart: Boolean

majestic: Boolean

interface Pet

type Cat implements Pet

id: ID!

name: String

...

sleepAmount: Int

curious: Boolean

id: ID!

name: String!

weight: Float

status: PetStatus

photo: Photo

dueDate: Date

inCareOf: Customer

type Dog implements Pet

id: ID!

name: String

...

good: Boolean

type Rabbit implements Pet

id: ID!

name: String

...

favoriteFood: String

floppy: Int

type Stingray 

implements Pet

id: ID!

name: String

...

chill: Boolean

fast: Boolean

type Horse 

implements Pet

id: ID!

name: String

...

streetsmart: Boolean

majestic: Boolean

type *TBDFuturePet 

implements Pet

id: ID!

name: String

...

newField: _____

newField: _____

Union Types

type Query {

    familyPets: [FamilyPets!]!

}

union FamilyPet = Cat | Dog

Query

query {
  familyPets {
    __typename
    ...on Cat {
      name
      weight
    }
    ...on Dog {
      name
      status
    }
  }
}

GraphQL is a spec that describes:

A Query Language

A Schema Definition Language

GraphQL Scalar Types

Int

Float

String

Boolean

ID

id: ID!

name: String!

GraphQL Scalar Types

type Photo {

      id: ID!

      name: String!

      url: String!

      description: String

      rating: Float

      private: Boolean!

}

GraphQL Object Types

name: String!

Nullable vs. Non-nullable

description: String

  type Query {

      totalUsers: Int!

  }

 

Root Queries

type User {

   postedPhotos: [Photo!]!

}

 

Lists

photos: [Photo]

Nullable vs. Non-nullable Lists

photos: [Photo]!

photos: [Photo!]!

Nullable list of nullable values

Non-nullable list of nullable values

Non-nullable list of non-nullable values

photos: [Photo!]

Nullable list of non-nullable values

Enums

 enum PhotoCategory {

      PORTRAIT

      ACTION

      LANDSCAPE

  }


One-to-One Connection

  type Photo {

      postedBy: User!

  }

 

One-to-Many Connection

type User {

   postedPhotos: [Photo!]!

}

 

Many-to-Many Connection

type Student {

      schedule: [Course!]!

}

type Course {

      students: [Student!]!

}

City to City

type City {

     name: String!

     connections: [City!]!

}

 

BOISE

SUN VALLEY

BEND

155 MILES

318 MILES

Through Types

type City {

     name: String!

     connections: [Connection!]!

}

 

type Connection {

     distance: Int!

     to: City!

}

BOISE

SUN VALLEY

155 MILES

BEND

318 MILES

Root Mutation

type Mutation {

    postPhoto: Boolean!

}

 

Arguments

type Mutation {

      postPhoto (name: String!): Photo!

 }

 

Input Types

input PostPhotoInput {

    name: String!

    category: PhotoCategory=PORTRAIT

    description: String

}

Input Types

 mutation addPhoto ($input: PostPhotoInput!) {

      postPhoto(input: $input) {

         id

         name

         url

  }  

}

{

   "input":  {

     "name": "Desert Sunset",

     "description": "Sunset over Sedona",

     "category": "LANDSCAPE"

   }

}

Query Variables

Root Subscription

type Subscription {

  newPhoto: Photo!

}

 

Custom Scalars

scalar DateTime

 

type Photo {

     created: DateTime!

     updated: DateTime!

}

Union Types

type Schedule {

    agenda: [AgendaItem!]!

}

union AgendaItem = StudyGroup | Workout

query {

    agenda {

        ...on Workout {

           name

           reps

       }

        ...on StudyGroup {

           name

           subject

           students

       }

  }

}

Query

Interfaces

interface ScheduleItem {

    name: String!

    start: Int

    end: Int

}

type StudyGroup implements ScheduleItem {

      name: String!

      start: Int

      end: Int

      students: Int!

}

type Workout implements ScheduleItem {

      name: Location!

      start: Int

      end: Int

      reps: Int!

}

type Query {

      agenda: [ScheduleItem!]!

}

enum PetCategory

DOG

CAT

STINGRAY

RABBIT

type Pet

id: ID!

name: String!

category: PetCategory!

        ...

HORSE

sleepAmount: Int

curious: Boolean

favoriteFood: String

floppy: Int

good: Boolean

chill: Boolean

fast: Boolean

streetsmart: Boolean

majestic: Boolean

interface Pet

type Cat implements Pet

id: ID!

name: String

...

sleepAmount: Int

curious: Boolean

id: ID!

name: String!

weight: Float

status: PetStatus

photo: Photo

dueDate: Date

inCareOf: Customer

type Dog implements Pet

id: ID!

name: String

...

good: Boolean

type Rabbit implements Pet

id: ID!

name: String

...

favoriteFood: String

floppy: Int

type Stingray 

implements Pet

id: ID!

name: String

...

chill: Boolean

fast: Boolean

type Horse 

implements Pet

id: ID!

name: String

...

streetsmart: Boolean

majestic: Boolean

type *TBDFuturePet 

implements Pet

id: ID!

name: String

...

newField: _____

newField: _____

Union Types

type Query {

    familyPets: [FamilyPets!]!

}

union FamilyPet = Cat | Dog

Query

query {
  familyPets {
    __typename
    ...on Cat {
      name
      weight
    }
    ...on Dog {
      name
      status
    }
  }
}

{ }

Query

Response

{ }

Query

Response

Gateway

{ }

Query

Response

Gateway

Reviews

Colors

Accounts

Queries

query {
  cat(name:"Biscuit") {
    name
    location
    mood
  }
}
{
  "data": {
    "cat": {
      "name":"Biscuit",
      "location": "Tahoe City",
      "mood": "pensive"
    }
  }
}

POST     /graphql

Query

Mutations

mutation {
  setLiftStatus(
    name:"Panorama", 
    newStatus: "hold"
  ) {
    name
    newStatus
    oldStatus
  }
}
{
  "data": {
    "setLiftStatus": {
      "name": "Panorama",
      "newStatus": "hold",
      "oldStatus": "open"
    }
  }
}

POST     /graphql

Mutation

Subscriptions

subscription {
  liftStatusChange {
    name
    newStatus
    oldStatus
  }
}
{
  "data": {
    "setLiftStatus": {
      "name": "Panorama",
      "newStatus": "hold",
      "oldStatus": "open"
    }
  }
}

WebSockets

Subscription

{
  "data": {
    "setLiftStatus": {
      "name": "Astra Express",
      "newStatus": "closed",
      "oldStatus": "open"
    }
  }
}
{
  "data": {
    "setLiftStatus": {
      "name": "Panorama",
      "newStatus": "closed",
      "oldStatus": "open"
    }
  }
}
query {
  cat(name: "Biscuit") {
    name
    location
    birthLocation
    weight
    gpa
    astrologicalSign
    hangingInThere
    bicyclePreference
    isADentist
    knowsADentist
    siblings {
      name
      location
    }
  }
}
query {
  cat(name: "Biscuit") {
    name
    location
    birthLocation
    weight
    gpa
    astrologicalSign
    hangingInThere
    bicyclePreference
    isADentist
    knowsADentist
    siblings {
      name
      location
    }
  }
}
query {
  cat(name: "Biscuit") {
    name
    location
    birthLocation
    
    
    
    
    
    
    
    
    
    
    
  }
}

@stream

@defer

@defer Directive

query {
  cat(name: "Biscuit") {
    name
    location
    birthLocation
    weight
    ...ExtraneousCatDetails @defer
  }
}

fragment ExtraneousCatDetails on Cat {
    gpa
    astrologicalSign
    hangingInThere
    bicyclePreference
    isADentist
    knowsADentist
}

@stream

query {
  cat(name: "Biscuit") {
    name
    friends {
      name
    }
  }
}
query {
  cat(name: "Biscuit") {
    name
    friends @stream(initialCount: 3) {
      name
    }
  }
}
query {
  cat(name: "Biscuit") {
    name
    friends @stream(initialCount: 3) {
      name
      ...ExtraneousCatFields @defer
    }
  }
}