Skip to content

Commit

Permalink
Render directives at the top of the schema (#1270)
Browse files Browse the repository at this point in the history
* Render directives at the top of the schema

* Remove extranous comma

* Remove repeatable statement from directives
  • Loading branch information
Fluxx authored Jan 28, 2022
1 parent d46b7cc commit 0714e10
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 4 deletions.
9 changes: 7 additions & 2 deletions core/src/main/scala/caliban/GraphQL.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package caliban

import caliban.CalibanError.ValidationError
import caliban.Rendering.renderTypes
import caliban.Rendering.{ renderDirectives, renderTypes }
import caliban.execution.{ ExecutionRequest, Executor, QueryExecution }
import caliban.introspection.Introspector
import caliban.introspection.adt._
Expand Down Expand Up @@ -45,7 +45,12 @@ trait GraphQL[-R] { self =>
|}""".stripMargin
}

s"""$schema
val directivesPrefix = renderDirectives(additionalDirectives) match {
case "" => ""
case directiveStr => directiveStr + "\n\n"
}

s"""${directivesPrefix}${schema}
|
|${renderTypes(schemaBuilder.types)}""".stripMargin
}
Expand Down
38 changes: 38 additions & 0 deletions core/src/main/scala/caliban/Rendering.scala
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,44 @@ object Rendering {
}
.mkString("\n\n")

def renderDirectives(directives: List[__Directive]): String =
directives.map(renderDirective).mkString("\n")

private def renderDirective(directive: __Directive): String = {
val inputs = directive.args match {
case i if i.nonEmpty => s"""(${i.map(renderInputValue).mkString(", ")})"""
case _ => ""
}
val locationStrings = directive.locations.map {
case __DirectiveLocation.QUERY => "QUERY"
case __DirectiveLocation.MUTATION => "MUTATION"
case __DirectiveLocation.SUBSCRIPTION => "SUBSCRIPTION"
case __DirectiveLocation.FIELD => "FIELD"
case __DirectiveLocation.FRAGMENT_DEFINITION => "FRAGMENT_DEFINITION"
case __DirectiveLocation.FRAGMENT_SPREAD => "FRAGMENT_SPREAD"
case __DirectiveLocation.INLINE_FRAGMENT => "INLINE_FRAGMENT"
case __DirectiveLocation.SCHEMA => "SCHEMA"
case __DirectiveLocation.SCALAR => "SCALAR"
case __DirectiveLocation.OBJECT => "OBJECT"
case __DirectiveLocation.FIELD_DEFINITION => "FIELD_DEFINITION"
case __DirectiveLocation.ARGUMENT_DEFINITION => "ARGUMENT_DEFINITION"
case __DirectiveLocation.INTERFACE => "INTERFACE"
case __DirectiveLocation.UNION => "UNION"
case __DirectiveLocation.ENUM => "ENUM"
case __DirectiveLocation.ENUM_VALUE => "ENUM_VALUE"
case __DirectiveLocation.INPUT_OBJECT => "INPUT_OBJECT"
case __DirectiveLocation.INPUT_FIELD_DEFINITION => "INPUT_FIELD_DEFINITION"
}
val directiveLocations = locationStrings.mkString(" | ")

val body = s"""directive @${directive.name}${inputs} on ${directiveLocations}""".stripMargin

renderDescription(directive.description) match {
case "" => body
case something => something + body
}
}

private def renderInterfaces(t: __Type): String =
t.interfaces()
.fold("")(_.flatMap(_.name) match {
Expand Down
7 changes: 5 additions & 2 deletions core/src/test/scala/caliban/RenderingSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ object RenderingSpec extends DefaultRunnableSpec {
override def spec: ZSpec[TestEnvironment, Any] =
suite("rendering")(
test("it should render directives") {
assert(graphQL(resolver).render.trim)(
equalTo("""schema {
assert(graphQL(resolver, directives = List(Directives.Test)).render.trim)(
equalTo(""""Test directive"
|directive @test(foo: Int) on FIELD_DEFINITION
|
|schema {
| query: Query
|}
|
Expand Down
18 changes: 18 additions & 0 deletions core/src/test/scala/caliban/TestUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import caliban.schema.Schema.scalarSchema
import caliban.schema.{ Schema, Types }
import zio.UIO
import zio.stream.ZStream
import caliban.introspection.adt.{ __Directive, __DirectiveLocation }

object TestUtils {

Expand Down Expand Up @@ -140,6 +141,23 @@ object TestUtils {
SubscriptionIO(ZStream.empty)
)

object Directives {
val Test = __Directive(
name = "test",
description = Some("Test directive"),
locations = Set(__DirectiveLocation.FIELD_DEFINITION),
args = List(
__InputValue(
"foo",
None,
() => Types.int,
None,
None
)
)
)
}

object InvalidSchemas {
case class DoubleUnderscoreArg(__name: String)
case class DoubleUnderscoreInputObjectArg(wrong: DoubleUnderscoreArg)
Expand Down

0 comments on commit 0714e10

Please sign in to comment.