GraphQL  Workshop

Eve Porcello

@eveporcello

eve@moonhighway.com

  • Intro to GraphQL
  • Understanding the Query Language
  • Working with GraphQL Schemas
  • Building a GraphQL Server

Agenda

  • 7:00AM - Start
  • 7:50 - 8:00 - Break
  • 8:50 - 9:00 - Break
  • 10:00 - End

Timing

  • You may know some of this
  • This is a workshop
  • When you have questions/ideas, always feel free to share

Things to Remember

GraphQL is a query language for your API.

{ }

{ }

Query

Response

DSL

How We Get Data with REST

/lifts/panorama

/trails/ocean-breeze

Noice!

/trails/songstress

/trails/hemmed-slacks

/trails/sandys

[
  {
    "name": "Panorama",
    "type": "gondola",
    "capacity": 8,
    "status": "open",
    "manufacturer": "Garaventa",
    "built": 2014,
    "summer": true,
    "night": false,
    "elevation_gain": 2800,
    "time": "9 minutes",
    "hours": "9:00am - 4:00pm",
    "updated": "9:45am",
    "trails": [
      "/class/api/snowtooth/trails/ocean-breeze",
      "/class/api/snowtooth/trails/songstress",
      "/class/api/snowtooth/trails/hemmed-slacks",
      "/class/api/snowtooth/trails/sandys"
    ]
  }
]
{
  "name": "Ocean Breeze",
  "lift": [
    "/class/api/snowtooth/lifts/panorama"
  ],
  "difficulty": "intermediate",
  "status": "open",
  "groomed": false,
  "snowmaking": false,
  "trees": true,
  "night": true
}
{
  "name": "Hemmed Slacks",
  "lift": [
    "/class/api/snowtooth/lifts/panorama"
  ],
  "difficulty": "intermediate",
  "status": "open",
  "groomed": false,
  "snowmaking": false,
  "trees": true,
  "night": false
}
{
  "name": "Songstress",
  "lift": [
    "/class/api/snowtooth/lifts/panorama"
  ],
  "difficulty": "expert",
  "status": "closed",
  "groomed": false,
  "snowmaking": false,
  "trees": true,
  "night": false
}
{
  "name": "Sandys",
  "lift": [
    "/class/api/snowtooth/lifts/astra-express",
    "/class/api/snowtooth/lifts/panorama"
  ],
  "difficulty": "intermediate",
  "status": "open",
  "groomed": false,
  "snowmaking": false,
  "trees": false,
  "night": false
}

/lifts/panorama

/trails/ocean-breeze

/trails/songstress

/trails/hemmed-slacks

/trails/sandys

How We Get Data with GraphQL

query {
  lift(name:"Panorama") {
    status
    trails {
      name
      status
    }
  }
}
{
  "data":{
    "lift":{
      "status":"hold",
      "trails": [
        {
          "name": "Hot Potato",
          "status": "open"
        },
        {
          "name": "West Elm",
          "status": "closed"
        }
      ]
    }
  }
}

POST     /graphql

Query

https://skiresort.com/graphql

How We Change Data with REST

/lifts/panorama

[
  {
    "name": "Panorama",
    "type": "gondola",
    "capacity": 8,
    "status": "open",
    "manufacturer": "Garaventa",
    "built": 2014,
    "summer": true,
    "night": false,
    "elevation_gain": 2800,
    "time": "9 minutes",
    "hours": "9:00am - 4:00pm",
    "updated": "9:45am",
    "trails": [
      "/class/api/snowtooth/trails/ocean-breeze",
      "/class/api/snowtooth/trails/songstress",
      "/class/api/snowtooth/trails/hemmed-slacks",
      "/class/api/snowtooth/trails/sandys"
    ]
  }
]

PUT

-H 'Content-Type: application/json'
-d { "status": "open" }

How We Change Data with GraphQL

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

POST     /graphql

Mutation

{ }

Query

Response

{ }

Query

Response

fn( )

fn( )

fn( )

fn( )

fn( )

fn( )

https://pet-library.moonhighway.com

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

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!]!

}

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!

}