GraphQL - a type system for your API
by Oleg Ilyenko / @easyangel
a.k.a. BFF (Backend For a Frontend)
A Data Query Language
query MyProduct {
  product(id: 123) {
    name
    description
    picture {
      width
      height
      url
    }
  }
}
          
{
  "data": {
    "product": {
      "name": "Delicious Cake",
      "description": "Just taste it!"
      "picture": {
        "width": 150,
        "height": 150,
        "url": "http://..."
      }
    }
  }
}
          
query MyProduct {
  products {
    picture(size: 300) {
      width, height, url
    }
  }
}
          
{
  "data": {
    "products": [
      {
        "picture": {
          "width": 300,
          "height": 300,
          "url": "http://..."
        }
      },
      ...
    ]
  }
}
          
query MyProduct {
  products {
    thumb: picture(size: 100) {
      width
    }
    fullSize: picture(size: 500) {
      width
    }
  }
}
          
{
  "data": {
    "products": [
      {
        "thumb": {
          "width": 100
        },
        "fullSize": {
          "width": 500
        }
      },
      ...
    ]
  }
}
          A Scala GraphQL Implementation
type Picture {
  width: Int!
  height: Int!
  url: String
}
          
case class Picture(
  width: Int,
  height: Int,
  url: Option[String]
)
          
val PictureType = ObjectType(
  "Picture",
  "The product picture",
  fields[Unit, Picture](
    Field("width", IntType,
      resolve = _.value.width),
    Field("height", IntType,
      resolve = _.value.height),
    Field("url", OptionType(StringType),
      description = Some("Picture CDN URL"),
      resolve = _.value.url)))
          
type Picture {
  width: Int!
  height: Int!
  url: String
}
          
case class Picture(
  width: Int,
  height: Int,
  url: Option[String]
)
          
val PictureType =
  deriveObjectType[Unit, Picture](
    ObjectTypeDescription("The product picture"),
    DocumentField("url", "Picture CDN URL"))
          
interface Identifiable {
  id: String!
}
          
trait Identifiable {
  def id: String
}
          
val IdentifiableType = InterfaceType(
  "Identifiable",
  "Entity that can be identified",
  fields[Unit, Identifiable](
    Field("id", StringType,
      resolve = _.value.id)))
          
type Product
    implements Identifiable {
  id: String!
  name: String!
  description: String
  picture(size: Int!): Picture
}
          
case class Product(
  id: String,
  name: String,
  description: String
) extends Identifiable {
  def picture(size: Int): Picture =
    Picture(
      width = size,
      height = size,
      url = Some(
        s"//cdn.com/$size/$id.jpg"))
}
          
val ProductType =
  deriveObjectType[Unit, Product](
    Interfaces(IdentifiableType),
    IncludeMethods("picture"))
          
type Query {
  product(id: Int!): Product
  products: [Product]
}
          
class ProductRepo {
  val Products = List(
    Product("1", "Cheesecake", "Tasty"),
    Product("2", "Health Potion", "+50 HP"))
  @GraphQLField
  def product(id: String) =
    Products find (_.id == id)
}
case class Ctx(repo: ProductRepo)
          
val QueryType =
  deriveContextObjectType[Ctx, ProductRepo, Unit](
    _.repo, ObjectTypeName("Query"))
          
val query =
  graphql"""
    query MyProduct {
      product(id: 2) {
        name
        description
        picture(size: 500) {
          width, height, url
        }
      }
    }
  """
          
val schema = Schema(QueryType)
val result: Future[Json] =
  Executor.execute(schema, query, Ctx(new ProductRepo))
          
{
  hero {
    id
    name
  }
}
// Response
{
  "data": {
    "hero": {
      "id": "2001",
      "name": "R2-D2"
    }
  }
}