Skip to content

Commit

Permalink
fix: Deprecated directive on handrolled fields (ghostdogpr#1168)
Browse files Browse the repository at this point in the history
* wip support deprecated on hand rolled schemas

* fix test

* set deprecated for fieldWithArgs as well

* Extract helpers
  • Loading branch information
frekw authored and Fluxx committed Jan 13, 2022
1 parent c8b6949 commit 6f10485
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 5 deletions.
18 changes: 17 additions & 1 deletion core/src/main/scala/caliban/parsing/adt/Directive.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
package caliban.parsing.adt

import caliban.InputValue
import caliban.{ InputValue, Value }

case class Directive(name: String, arguments: Map[String, InputValue] = Map.empty, index: Int = 0)

object Directives {
def isDeprecated(directives: List[Directive]): Boolean =
directives.exists(_.name == "deprecated")

def deprecationReason(directives: List[Directive]): Option[String] =
directives.collectFirst {
case f if f.name == "deprecated" =>
f.arguments
.get("reason")
.flatMap(_ match {
case Value.StringValue(value) => Some(value)
case _ => None
})
}.flatten
}
17 changes: 13 additions & 4 deletions core/src/main/scala/caliban/schema/Schema.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import caliban.ResponseValue._
import caliban.Value._
import caliban.execution.Field
import caliban.introspection.adt._
import caliban.parsing.adt.Directive
import caliban.parsing.adt.{ Directive, Directives }
import caliban.schema.Step._
import caliban.schema.Types._
import caliban.uploads.Upload
Expand Down Expand Up @@ -144,7 +144,6 @@ trait GenericSchema[R] extends SchemaDerivation[R] with TemporalSchema {
directives: List[Directive] = List.empty
): Schema[R1, A] =
new Schema[R1, A] {

override def toType(isInput: Boolean, isSubscription: Boolean): __Type =
if (isInput) {
makeInputObject(
Expand Down Expand Up @@ -612,7 +611,9 @@ abstract class PartiallyAppliedFieldBase[V](name: String, description: Option[St
() =>
if (ev.optional) ev.toType_(ft.isInput, ft.isSubscription)
else Types.makeNonNull(ev.toType_(ft.isInput, ft.isSubscription)),
directives = Some(directives).filter(_.nonEmpty)
isDeprecated = Directives.isDeprecated(directives),
deprecationReason = Directives.deprecationReason(directives),
directives = Some(directives.filter(_.name != "deprecated")).filter(_.nonEmpty)
)
}

Expand All @@ -635,7 +636,15 @@ case class PartiallyAppliedFieldLazy[V](name: String, description: Option[String
case class PartiallyAppliedFieldWithArgs[V, A](name: String, description: Option[String], directives: List[Directive]) {
def apply[R, V1](fn: V => (A => V1))(implicit ev1: Schema[R, A => V1], fa: FieldAttributes): (__Field, V => Step[R]) =
(
__Field(name, description, ev1.arguments, () => ev1.toType_(fa.isInput, fa.isSubscription)),
__Field(
name,
description,
ev1.arguments,
() => ev1.toType_(fa.isInput, fa.isSubscription),
isDeprecated = Directives.isDeprecated(directives),
deprecationReason = Directives.deprecationReason(directives),
directives = Some(directives.filter(_.name != "deprecated")).filter(_.nonEmpty)
),
(v: V) => ev1.resolve(fn(v))
)
}
58 changes: 58 additions & 0 deletions core/src/test/scala/caliban/execution/ExecutionSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,64 @@ object ExecutionSpec extends DefaultRunnableSpec {
)
)
},
testM("directives on hand-rolled schema") {
import Schema._
import caliban.parsing.adt.Directive

case class Foo(fieldA: String => String = _ => "foo", fieldB: String = "foo")

implicit lazy val fooSchema: Schema[Any, Foo] = obj("Foo", None)(implicit ft =>
List(
fieldWithArgs(
"fieldA",
Some("Description"),
List(
Directive(
"deprecated",
Map(
"reason" -> Value.StringValue("due to reasons")
)
)
)
)(_.fieldA),
field(
"fieldB",
Some("Description"),
List(
Directive(
"deprecated",
Map(
"reason" -> Value.StringValue("due to reasons")
)
)
)
)(_.fieldB)
)
)

case class Queries(foo: Foo)

val queries: Queries = Queries(Foo())

val api: GraphQL[Any] = GraphQL.graphQL(RootResolver(queries))
val interpreter = api.interpreter

val query = gqldoc("""{
__type(name: "Foo") {
name
fields(includeDeprecated: true) {
name
isDeprecated
deprecationReason
}
}
}""")

val expected =
"""{"__type":{"name":"Foo","fields":[{"name":"fieldA","isDeprecated":true,"deprecationReason":"due to reasons"},{"name":"fieldB","isDeprecated":true,"deprecationReason":"due to reasons"}]}}"""

assertM(interpreter.flatMap(_.execute(query)).map(_.data.toString))(equalTo(expected))
},
testM("union redirect") {
sealed trait Foo

Expand Down

0 comments on commit 6f10485

Please sign in to comment.