Starting Schema
We will be making a group chat app (without the user authentication)
#
Write a SchemaLet's look at what the final schema look like:
Feel free to customize the schema to your liking
schema.graphql
type Message { id: ID! content: String! authorName: String! createdAt: String!}
type Query { messages(limit: Int! = 30): [Message!]! messageBy(authorName: String!): [Message!]!}
type Mutation { send(msg: String!, by: String!): Message!}
type Subscription { roomLobby: Message!}
#
Sangria Required TypesSangria Schema are written with a required context and root value type. So, let's create a basic context type that can be updated later on.
Stub context case class
Context.scala
case class Context( // Will be added later)
#
Sangria Object TypesI am assumming some sangria knowledge here. Let's create all the proper object types excluding the subscription.
#
Message Object TypeMessage.scala
import sangria.schema._import sangria.macros.derive._import /*path to file*/.Contextimport java.time.Instant
case class Message( id: String, content: String, authorName: String,) { val createdAt: String = Instant.now().toString}
object Message { val t = deriveObjectType[Context, Message]( AddFields( Field("createdAt", StringType, resolve = _.value.createdAt) ) )}
Equivalent ObjectType (from the GraphQL SDL)
type Message { id: ID! content: String! authorName: String! createdAt: String!}
#
Root / Top Level ObjectNow, we have all the ObjectType
that isn't a RootOperationType. We can start writing the top level objects primarily the Query
and Mutation
as the Subscription
require a bit more work which will be described on the next page.
Schema.scala
import sangria.schema._import scala.math.minimport java.util.UUIDimport /*path to file*/.Contextimport /*path to file*/.Message
object Schema { val limitArg = Argument("limit", IntType, defaultValue = 30) val authorNameArg = Argument("authorName", StringType)
val QueryType = ObjectType( "Query", fields[Context, Unit]( Field("messages", ListType(Message.t), arguments = limitArg :: Nil, // We will be updating this later on resolve = c => List[Message]().reverse.take(min(c.arg(limitArg), 100)) ), Field("messageBy", ListType(Message.t), arguments = authorNameArg :: Nil, // We will be updating this later on resolve = c => List[Message]().reverse.filter(_.authorName == c.arg(authorNameArg)) ) ) )
val (byArg, msgArg) = ( Argument("by", StringType), Argument("msg", StringType) )
val MutationType = ObjectType( "Mutation", fields[Context, Unit]( Field("send", ListType(Message.t), arguments = msgArg :: byArg :: Nil, // We will be updating this later on resolve = c => Message( id = UUID.randomUUID().toString, content = c.arg(msgArg), authorName = c.arg(byArg) ) ) ) )
val t = Schema(QueryType, Some(MutationType))}
Equivalent ObjectType (from the GraphQL SDL)
type Query { messages(limit: Int! = 30): [Message!]! messageBy(authorName: String!): [Message!]!}
type Mutation { send(msg: String!, by: String!): Message!}
Although the resolvers are incomplete due to lack of data, We already put in place the appropriate logic so it will be an easy refactor.