diff --git a/core/src/main/scala-2/caliban/schema/SchemaDerivation.scala b/core/src/main/scala-2/caliban/schema/SchemaDerivation.scala index 69f950b1b..defc2f192 100644 --- a/core/src/main/scala-2/caliban/schema/SchemaDerivation.scala +++ b/core/src/main/scala-2/caliban/schema/SchemaDerivation.scala @@ -199,8 +199,14 @@ trait CommonSchemaDerivation[R] { .getOrElse(customizeInputTypeName(getName(ctx)))), getDescription(ctx), ctx.subtypes.toList.flatMap { p => - p.typeclass.toType_(isInput = true).allInputFields.map(_.nullable) - }, + val pTpe = p.typeclass.toType_(isInput = true) + pTpe.allInputFields.map { t => + t.nullable.copy( + description = t.description.orElse(pTpe.description), + directives = t.directives.orElse(pTpe.directives) + ) + } + }.sortBy(_.name), Some(ctx.typeName.full), Some(List(Directive(Directives.OneOf))) ) diff --git a/core/src/main/scala-3/caliban/schema/DerivationUtils.scala b/core/src/main/scala-3/caliban/schema/DerivationUtils.scala index cc1469057..12acd8043 100644 --- a/core/src/main/scala-3/caliban/schema/DerivationUtils.scala +++ b/core/src/main/scala-3/caliban/schema/DerivationUtils.scala @@ -130,7 +130,15 @@ private object DerivationUtils { makeInputObject( Some(getInputName(annotations).getOrElse(customizeInputTypeName(getName(annotations, info)))), getDescription(annotations), - schemas.flatMap(_.toType_(isInput = true).allInputFields.map(_.nullable)), + schemas.flatMap { s => + val pTpe = s.toType_(isInput = true) + pTpe.allInputFields.map { t => + t.nullable.copy( + description = t.description.orElse(pTpe.description), + directives = t.directives.orElse(pTpe.directives) + ) + } + }.sortBy(_.name), Some(info.full), Some(List(Directive(Directives.OneOf))) ) diff --git a/core/src/test/scala-3/caliban/schema/ArgBuilderDerivesAutoSpec.scala b/core/src/test/scala-3/caliban/schema/ArgBuilderDerivesAutoSpec.scala index 74dcb8176..1e9ee926e 100644 --- a/core/src/test/scala-3/caliban/schema/ArgBuilderDerivesAutoSpec.scala +++ b/core/src/test/scala-3/caliban/schema/ArgBuilderDerivesAutoSpec.scala @@ -5,7 +5,8 @@ import caliban.CalibanError.ExecutionError import caliban.InputValue.{ ListValue, ObjectValue } import caliban.Macros.gqldoc import caliban.Value.{ IntValue, NullValue, StringValue } -import caliban.schema.Annotations.GQLOneOfInput +import caliban.parsing.adt.Directive +import caliban.schema.Annotations.{ GQLDescription, GQLDirective, GQLOneOfInput } import caliban.schema.ArgBuilder.* import zio.ZIO import zio.test.* @@ -70,8 +71,8 @@ object ArgBuilderDerivesAutoSpec extends ZIOSpecDefault { suite("enums as oneOf inputs") { @GQLOneOfInput enum Foo derives Schema.SemiAuto, ArgBuilder { - case FooString(stringValue: String) extends Foo - case FooInt(intValue: Int) extends Foo + @GQLDescription("fooString") case FooString(stringValue: String) extends Foo + @GQLDirective(Directive("intDirective")) case FooInt(intValue: Int) extends Foo } case class Wrapper(fooInput: Foo) derives Schema.SemiAuto, ArgBuilder case class Queries(foo: Wrapper => String, fooUnwrapped: Foo => String) derives Schema.SemiAuto @@ -84,8 +85,9 @@ object ArgBuilderDerivesAutoSpec extends ZIOSpecDefault { |} | |input FooInput @oneOf { + | intValue: Int @intDirective + | "fooString" | stringValue: String - | intValue: Int |} | |type Queries { diff --git a/core/src/test/scala/caliban/RenderingSpec.scala b/core/src/test/scala/caliban/RenderingSpec.scala index d05b6679d..2281fc116 100644 --- a/core/src/test/scala/caliban/RenderingSpec.scala +++ b/core/src/test/scala/caliban/RenderingSpec.scala @@ -204,10 +204,10 @@ object RenderingSpec extends ZIOSpecDefault { |} | |input FooInput @oneOf { - | stringValue: String - | otherStringField: String | intValue: FooIntInput | otherIntField: FooInt2Input + | otherStringField: String + | stringValue: String |} | |input FooInt2Input { diff --git a/core/src/test/scala/caliban/schema/SchemaSpec.scala b/core/src/test/scala/caliban/schema/SchemaSpec.scala index 636c59bb4..791b7fadb 100644 --- a/core/src/test/scala/caliban/schema/SchemaSpec.scala +++ b/core/src/test/scala/caliban/schema/SchemaSpec.scala @@ -389,6 +389,27 @@ object SchemaSpec extends ZIOSpecDefault { | mid2: Mid2! |}""".stripMargin ) + }, + test("annotations on leaf classes of OneOfInput are added to the input object fields") { + case class Query(value: MyOneOfInput => String) + + val schema = graphQL(RootResolver(Query(_.toString))).render + println(schema) + assertTrue( + schema == """schema { + | query: Query + |} + | + |input MyOneOfInput @oneOf { + | "foo input" + | a: Int + | b: String @barDirective + |} + | + |type Query { + | value(value: MyOneOfInput!): String! + |}""".stripMargin + ) } ) @@ -460,4 +481,14 @@ object SchemaSpec extends ZIOSpecDefault { case class FooB(b: String, c: String, d: String) extends Mid1 with Mid2 case class FooC(b: String, d: String, e: String) extends Mid2 } + + @GQLOneOfInput + sealed trait MyOneOfInput + + object OneOfInput { + @GQLDescription("foo input") + case class Foo(a: Int) extends MyOneOfInput + @GQLDirective(Directive("barDirective")) + case class Bar(b: String) extends MyOneOfInput + } }