Created
June 26, 2018 10:08
-
-
Save marioosh/6f75f24bb5e5fd6fc3d46472147c4551 to your computer and use it in GitHub Desktop.
HowToGraphql - Sangria tutorial - Interfaces
This file contains 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
package com.howtographql.scala.sangria\ | |
import DBSchema._ | |
import com.howtographql.scala.sangria.models.{Link, User, Vote} | |
import slick.jdbc.H2Profile.api._ | |
import scala.concurrent.Future | |
class DAO(db: Database) { | |
def allLinks = db.run(Links.result) | |
def getLinks(ids: Seq[Int]): Future[Seq[Link]] = db.run( | |
Links.filter(_.id inSet ids).result | |
) | |
def getUsers(ids: Seq[Int]): Future[Seq[User]] = db.run( | |
Users.filter(_.id inSet ids).result | |
) | |
def getVotes(ids: Seq[Int]): Future[Seq[Vote]] = { | |
db.run( | |
Votes.filter(_.id inSet ids).result | |
) | |
} | |
} |
This file contains 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
package com.howtographql.scala.sangria | |
import java.sql.Timestamp | |
import akka.http.scaladsl.model.DateTime | |
import com.howtographql.scala.sangria.models._ | |
import slick.jdbc.H2Profile.api._ | |
import scala.concurrent.duration._ | |
import scala.concurrent.Await | |
import scala.language.postfixOps | |
object DBSchema { | |
implicit val dateTimeColumnType = MappedColumnType.base[DateTime, Timestamp]( | |
dt => new Timestamp(dt.clicks), | |
ts => DateTime(ts.getTime) | |
) | |
class LinksTable(tag: Tag) extends Table[Link](tag, "LINKS"){ | |
def id = column[Int]("ID", O.PrimaryKey, O.AutoInc) | |
def url = column[String]("URL") | |
def description = column[String]("DESCRIPTION") | |
def createdAt = column[DateTime]("CREATED_AT") | |
def * = (id, url, description, createdAt).mapTo[Link] | |
} | |
val Links = TableQuery[LinksTable] | |
class UsersTable(tag: Tag) extends Table[User](tag, "USERS"){ | |
def id = column[Int]("ID", O.PrimaryKey, O.AutoInc) | |
def name = column[String]("NAME") | |
def email = column[String]("EMAIL") | |
def password = column[String]("PASSWORD") | |
def createdAt = column[DateTime]("CREATED_AT") | |
def * = (id, name, email, password, createdAt).mapTo[User] | |
} | |
val Users = TableQuery[UsersTable] | |
class VotesTable(tag: Tag) extends Table[Vote](tag, "VOTES"){ | |
def id = column[Int]("ID", O.PrimaryKey, O.AutoInc) | |
def userId = column[Int]("USER_ID") | |
def linkId = column[Int]("LINK_ID") | |
def createdAt = column[DateTime]("CREATED_AT") | |
def * = (id, userId, linkId, createdAt).mapTo[Vote] | |
} | |
val Votes = TableQuery[VotesTable] | |
/** | |
* Load schema and populate sample data withing this Sequence od DBActions | |
*/ | |
val databaseSetup = DBIO.seq( | |
Links.schema.create, | |
Users.schema.create, | |
Votes.schema.create, | |
Links forceInsertAll Seq( | |
Link(1, "http://howtographql.com", "Awesome community driven GraphQL tutorial", DateTime(2017,9,12)), | |
Link(2, "http://graphql.org", "Official GraphQL web page",DateTime(2017,10,1)), | |
Link(3, "https://facebook.github.io/graphql/", "GraphQL specification",DateTime(2017,10,2)) | |
), | |
Users forceInsertAll Seq( | |
User(1, "mario", "mario@example.com", "s3cr3t"), | |
User(2, "Fred", "fred@flinstones.com", "wilmalove") | |
), | |
Votes forceInsertAll Seq( | |
Vote(id = 1, userId = 1, linkId = 1), | |
Vote(id = 2, userId = 1, linkId = 2), | |
Vote(id = 3, userId = 1, linkId = 3), | |
Vote(id = 4, userId = 2, linkId = 2), | |
) | |
) | |
def createDatabase: DAO = { | |
val db = Database.forConfig("h2mem") | |
Await.result(db.run(databaseSetup), 10 seconds) | |
new DAO(db) | |
} | |
} |
This file contains 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
package com.howtographql.scala.sangria | |
import akka.http.scaladsl.model.DateTime | |
import sangria.schema.{ListType, ObjectType} | |
import models._ | |
import sangria.ast.StringValue | |
import sangria.execution.deferred.{DeferredResolver, Fetcher, HasId} | |
import sangria.schema._ | |
import sangria.macros.derive._ | |
object GraphQLSchema { | |
implicit val GraphQLDateTime = ScalarType[DateTime](//1 | |
"DateTime",//2 | |
coerceOutput = (dt, _) => dt.toString, //3 | |
coerceInput = { //4 | |
case StringValue(dt, _, _ ) => DateTime.fromIsoDateTimeString(dt).toRight(DateTimeCoerceViolation) | |
case _ => Left(DateTimeCoerceViolation) | |
}, | |
coerceUserInput = { //5 | |
case s: String => DateTime.fromIsoDateTimeString(s).toRight(DateTimeCoerceViolation) | |
case _ => Left(DateTimeCoerceViolation) | |
} | |
) | |
val IdentifiableType = InterfaceType( | |
"Identifiable", | |
fields[Unit, Identifiable]( | |
Field("id", IntType, resolve = _.value.id) | |
) | |
) | |
val LinkType = deriveObjectType[Unit, Link]( | |
Interfaces(IdentifiableType), | |
ReplaceField("createdAt", Field("createdAt", GraphQLDateTime, resolve = _.value.createdAt)) | |
) | |
val UserType = deriveObjectType[Unit, User]( | |
Interfaces(IdentifiableType) | |
) | |
val VoteType = deriveObjectType[Unit, Vote]( | |
Interfaces(IdentifiableType) | |
) | |
val linksFetcher = Fetcher( | |
(ctx: MyContext, ids: Seq[Int]) => ctx.dao.getLinks(ids) | |
) | |
val usersFetcher = Fetcher( | |
(ctx: MyContext, ids: Seq[Int]) => ctx.dao.getUsers(ids) | |
) | |
val votesFetcher = Fetcher( | |
(ctx: MyContext, ids: Seq[Int]) => ctx.dao.getVotes(ids) | |
) | |
val Resolver = DeferredResolver.fetchers(linksFetcher, usersFetcher, votesFetcher) | |
val Id = Argument("id", IntType) | |
val Ids = Argument("ids", ListInputType(IntType)) | |
val QueryType = ObjectType( | |
"Query", | |
fields[MyContext, Unit]( | |
Field("allLinks", ListType(LinkType), resolve = c => c.ctx.dao.allLinks), | |
Field("link", | |
OptionType(LinkType), | |
arguments = Id :: Nil, | |
resolve = c => linksFetcher.deferOpt(c.arg(Id)) | |
), | |
Field("links", | |
ListType(LinkType), | |
arguments = Ids :: Nil, | |
resolve = c => linksFetcher.deferSeq(c.arg(Ids)) | |
), | |
Field("users", | |
ListType(UserType), | |
arguments = List(Ids), | |
resolve = c => usersFetcher.deferSeq(c.arg(Ids)) | |
), | |
Field("votes", | |
ListType(VoteType), | |
arguments = List(Ids), | |
resolve = c => votesFetcher.deferSeq(c.arg(Ids)) | |
) | |
) | |
) | |
val SchemaDefinition = Schema(QueryType) | |
} |
This file contains 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
package com.howtographql.scala.sangria | |
import akka.http.scaladsl.model.DateTime | |
import sangria.execution.deferred.HasId | |
import sangria.validation.Violation | |
package object models { | |
trait Identifiable { | |
val id: Int | |
} | |
object Identifiable { | |
implicit def hasId[T <: Identifiable]: HasId[T, Int] = HasId(_.id) | |
} | |
case class Link(id: Int, url: String, description: String, createdAt: DateTime) extends Identifiable | |
case object DateTimeCoerceViolation extends Violation { | |
override def errorMessage: String = "Error during parsing DateTime" | |
} | |
case class User(id: Int, name: String, email: String, password: String, createdAt: DateTime = DateTime.now) extends Identifiable | |
case class Vote(id: Int, userId: Int, linkId: Int, createdAt: DateTime = DateTime.now) extends Identifiable | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment