Skip to content

Instantly share code, notes, and snippets.

@martyphee
Created August 12, 2021 11:25
Show Gist options
  • Save martyphee/edb358d241b3333bf1e705aa55daad51 to your computer and use it in GitHub Desktop.
Save martyphee/edb358d241b3333bf1e705aa55daad51 to your computer and use it in GitHub Desktop.
Sangria Banana example
import com.typesafe.scalalogging.LazyLogging
import sangria.execution.Executor
import sangria.macros._
import sangria.marshalling.sprayJson._
import sangria.schema.{Argument, DirectiveLocation => DL, _}
import spray.json._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.io.StdIn
import scala.util.{Failure, Success}
object Banana extends App with LazyLogging {
val schemaAst =
gql"""
enum Color {
Red, Green, Blue
}
interface Fruit {
id: ID!
}
type Apple implements Fruit {
id: ID!
color: Color
}
type Banana implements Fruit {
id: ID!
length: Int
type: String
}
type Query @addSpecial {
fruit: Fruit
bananas: [Fruit] @generateBananas(count: 3)
}
"""
val CountArg = Argument("count", IntType)
val GenerateBananasDir = Directive(
"generateBananas",
arguments = CountArg :: Nil,
locations = Set(DL.FieldDefinition)
)
val AddSpecialDir = Directive("addSpecial", locations = Set(DL.Object))
val builder = AstSchemaBuilder.resolverBased[Unit](
// Requirement #1 - provides appropriate instance check based on the `type` JSON field
InstanceCheck.field[Unit, JsValue],
// Requirement #2 - defined a resolution logic based on the `@generateBananas` directive
DirectiveResolver(
GenerateBananasDir,
c =>
(1 to c.arg(CountArg)) map (id =>
JsObject(
"type" -> JsString("Banana"),
"id" -> JsString(id.toString),
"length" -> JsNumber(id * 10)
)
)
),
// Requirement #3 - add extra field based on the `@addSpecial` directive
DirectiveFieldProvider(
AddSpecialDir,
c =>
MaterializedField(
StandaloneOrigin,
Field(
"specialFruit",
c.objectType("Banana"),
resolve =
ResolverBasedAstSchemaBuilder.extractFieldValue[Unit, JsValue]
)
) :: Nil
),
// Requirement #4 - provides default behaviour for all other fields
FieldResolver.defaultInput[Unit, JsValue]
)
val schema = Schema.buildFromAst(
schemaAst,
builder.validateSchemaWithException(schemaAst)
)
val query =
gql"""
{
fruit {
id
... on Apple {color}
... on Banana {length}
}
bananas {
... on Banana {length}
}
specialFruit {
id
type
}
}
"""
val initialData =
"""
{
"fruit": {
"type": "Apple",
"id": "1",
"color": "Red"
},
"specialFruit": {
"type": "Apple",
"id": "42",
"color": "Blue"
}
}
""".parseJson
Executor.execute(schema, query, root = initialData) onComplete {
case Success(value) => println(value)
case Failure(value) => println(value)
}
Runtime
.getRuntime()
.addShutdownHook(new Thread {
override def run = {
System.out.println("Shutdown hook ran")
// if (socket != null) socket.close()
// Thread.sleep(125)
}
})
logger.info(
s"Server online\nPress RETURN to stop..."
)
StdIn.readLine()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment