diff --git a/core/src/main/scala-2/caliban/schema/SchemaVersionSpecific.scala b/core/src/main/scala-2/caliban/schema/SchemaVersionSpecific.scala new file mode 100644 index 000000000..e601e2c0b --- /dev/null +++ b/core/src/main/scala-2/caliban/schema/SchemaVersionSpecific.scala @@ -0,0 +1,3 @@ +package caliban.schema + +trait SchemaVersionSpecific diff --git a/core/src/main/scala-3/caliban/schema/SchemaVersionSpecific.scala b/core/src/main/scala-3/caliban/schema/SchemaVersionSpecific.scala new file mode 100644 index 000000000..7d3baf6a9 --- /dev/null +++ b/core/src/main/scala-3/caliban/schema/SchemaVersionSpecific.scala @@ -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) + } + +} diff --git a/core/src/main/scala/caliban/schema/Schema.scala b/core/src/main/scala/caliban/schema/Schema.scala index 069e40194..404604e2a 100644 --- a/core/src/main/scala/caliban/schema/Schema.scala +++ b/core/src/main/scala/caliban/schema/Schema.scala @@ -156,7 +156,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 { @@ -325,6 +325,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])] diff --git a/core/src/test/scala-3/caliban/schema/SchemaDerivesAutoSpec.scala b/core/src/test/scala-3/caliban/schema/SchemaDerivesAutoSpec.scala index 7475cfe8f..1478bf258 100644 --- a/core/src/test/scala-3/caliban/schema/SchemaDerivesAutoSpec.scala +++ b/core/src/test/scala-3/caliban/schema/SchemaDerivesAutoSpec.scala @@ -273,6 +273,7 @@ object SchemaDerivesAutoSpec extends ZIOSpecDefault { |type A { | a: String! + | b: Int |} |type Queries { @@ -280,10 +281,10 @@ object SchemaDerivesAutoSpec extends ZIOSpecDefault { |}""".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) @@ -292,10 +293,10 @@ 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) @@ -303,9 +304,10 @@ object SchemaDerivesAutoSpec extends ZIOSpecDefault { 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 @@ -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