Last active
March 1, 2016 19:58
-
-
Save OlegIlyenko/b36891a7bfc272e7db33 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sangria.schema._ | |
import sangria.ast | |
import sangria.macros._ | |
import sangria.execution._ | |
case class MyContext(originalQuery: ast.Document) { | |
def loadEntity(id: String, typeHints: Set[String]): Option[Identifiable] = { | |
println(typeHints) | |
None // your entity loagic goes here | |
} | |
} | |
trait Identifiable { | |
def id: String | |
} | |
case class Account(id: String, name: Option[String]) extends Identifiable | |
case class Order(id: String, orderNumber: String) extends Identifiable | |
val IdentifiableType = InterfaceType("Identifiable", fields[Unit, Identifiable]( | |
Field("id", StringType, resolve = _.value.id))) | |
val AccountType = ObjectType("Account", interfaces[Unit, Account](IdentifiableType), | |
fields[Unit, Account]( | |
Field("name", OptionType(StringType), resolve = _.value.name))) | |
val OrderType = ObjectType("Order", interfaces[Unit, Order](IdentifiableType), | |
fields[Unit, Order]( | |
Field("orderNumber", StringType, resolve = _.value.orderNumber))) | |
val IdArg = Argument("id", StringType) | |
// Collects all of the fragment type conditions. | |
// Please note, that directives are not considered here. It's posible that | |
// particular directive will exclude the fragment. Ideally such fragments should be ignored | |
def collectTypeConditions(query: ast.Document, fields: Vector[ast.Field]) = | |
fields.toSet.flatMap((field: ast.Field) ⇒ field.selections.collect { | |
case ast.InlineFragment(Some(ast.NamedType(name, _)), _, _, _) ⇒ | |
name | |
case ast.FragmentSpread(name, _, _) ⇒ | |
query.fragments(name).typeCondition.name | |
}) | |
val QueryType = ObjectType("Query", fields[MyContext, Unit]( | |
Field("node", OptionType(IdentifiableType), | |
arguments = IdArg :: Nil, | |
resolve = c ⇒ { | |
val possibleTypes = collectTypeConditions(c.ctx.originalQuery, c.astFields) | |
c.ctx.loadEntity(c.arg(IdArg), typeHints = possibleTypes) | |
}))) | |
val schema = Schema(QueryType, additionalTypes = AccountType :: OrderType :: Nil) | |
val query = | |
graphql""" | |
query myQuery1 { | |
node(id: "123") { | |
id | |
__typename | |
...MyAccountFrag | |
} | |
} | |
query myQuery2 { | |
node(id: "123") { | |
id | |
__typename | |
... on Order { | |
orderNumber | |
} | |
} | |
} | |
query myQuery3 { | |
node(id: "123") { | |
id | |
__typename | |
...MyAccountFrag | |
...MyOrderFrag | |
} | |
} | |
fragment MyAccountFrag on Account { | |
name | |
} | |
fragment MyOrderFrag on Order { | |
orderNumber | |
} | |
""" | |
Executor.execute(schema, query, Some("myQuery1"), userContext = MyContext(query)).await | |
Executor.execute(schema, query, Some("myQuery2"), userContext = MyContext(query)).await | |
Executor.execute(schema, query, Some("myQuery3"), userContext = MyContext(query)).await | |
// Will print: | |
// Set(Account) | |
// Set(Order) | |
// Set(Account, Order) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment