Skip to content

Commit

Permalink
Add Scala 3-specific method for building custom schemas (#2211)
Browse files Browse the repository at this point in the history
* Add Scala 3-specific method for building custom schemas

* Fix scaladoc

* PR comment

* Rename customObj in scaladoc
  • Loading branch information
kyri-petrou authored May 6, 2024
1 parent b88f156 commit fa51e3a
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package caliban.schema

trait SchemaVersionSpecific
33 changes: 33 additions & 0 deletions core/src/main/scala-3/caliban/schema/SchemaVersionSpecific.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package caliban.schema

import caliban.introspection.adt.__Field
import caliban.parsing.adt.Directive

transparent trait SchemaVersionSpecific extends GenericSchema[Any] {

/**
* Scala 3 variant of the `obj` method which improves UX for creating custom object schemas.
*
* {{{
* case class Author(id: String, firstName: String, lastName: String)
*
* given Schema[Any, Author] = Schema.customObj("Author")(
* field("id")(_.id),
* field("fullName")(author => s"${author.firstName} ${author.lastName}"),
* )
* }}}
*
* @see [[caliban.schema.GenericSchema.obj]]
*/
def customObj[R1, V](
name: String,
description: Option[String] = None,
directives: List[Directive] = Nil
)(
fields: FieldAttributes ?=> (__Field, V => Step[R1])*
): Schema[R1, V] =
obj(name, description, directives) { case given FieldAttributes =>
fields.toList.map(identity)
}

}
4 changes: 3 additions & 1 deletion core/src/main/scala/caliban/schema/Schema.scala
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ trait Schema[-R, T] { self =>
}
}

object Schema extends GenericSchema[Any]
object Schema extends GenericSchema[Any] with SchemaVersionSpecific

trait GenericSchema[R] extends SchemaDerivation[R] with TemporalSchema {

Expand Down Expand Up @@ -311,6 +311,8 @@ trait GenericSchema[R] extends SchemaDerivation[R] with TemporalSchema {
* )
*
* }}}
*
* @see `customObj` for an improved variant using context functions (Scala 3 only)
*/
def obj[R1, V](name: String, description: Option[String] = None, directives: List[Directive] = Nil)(
fields: FieldAttributes => List[(__Field, V => Step[R1])]
Expand Down
23 changes: 13 additions & 10 deletions core/src/test/scala-3/caliban/schema/SchemaDerivesAutoSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -273,17 +273,18 @@ object SchemaDerivesAutoSpec extends ZIOSpecDefault {
|type A {
| a: String!
| b: Int
|}
|type Queries {
| as: [A!]!
|}""".stripMargin
List(
test("from GenericSchema[Any]") {
case class A(a: String)
case class A(a: String, b: Option[Int])
case class Queries(as: List[A]) derives Schema.Auto

val resolver = RootResolver(Queries(List(A("a"), A("b"))))
val resolver = RootResolver(Queries(List(A("a", None), A("b", None))))
val gql = graphQL(resolver)

assertTrue(gql.render == expected)
Expand All @@ -292,20 +293,21 @@ object SchemaDerivesAutoSpec extends ZIOSpecDefault {
trait Foo
object FooSchema extends SchemaDerivation[Foo]

case class A(a: String)
case class A(a: String, b: Option[Int])
case class Queries(as: List[A]) derives FooSchema.Auto

val resolver = RootResolver(Queries(List(A("a"), A("b"))))
val resolver = RootResolver(Queries(List(A("a", None), A("b", None))))
val gql = graphQL(resolver)

assertTrue(gql.render == expected)
},
test("from local scope") {
case class A(a: Int)

given Schema[Any, A] = Schema.obj[Any, A]("A") { case given FieldAttributes =>
List(Schema.field("a")(_.a.toString))
}
given Schema[Any, A] = Schema.customObj[Any, A]("A")(
Schema.field("a")(_.a.toString),
Schema.field("b")(v => Option(v.a))
)

case class Queries(as: List[A]) derives Schema.Auto

Expand All @@ -319,9 +321,10 @@ object SchemaDerivesAutoSpec extends ZIOSpecDefault {
object FooSchema extends SchemaDerivation[Foo]
case class A(a: Int)

given Schema[Any, A] = Schema.obj[Any, A]("A") { case given FieldAttributes =>
List(Schema.field("a")(_.a.toString))
}
given Schema[Any, A] = Schema.customObj[Any, A]("A")(
Schema.field("a")(_.a.toString),
Schema.field("b")(v => Option(v.a))
)

case class Queries(as: List[A]) derives FooSchema.Auto

Expand Down

0 comments on commit fa51e3a

Please sign in to comment.