Skip to content

Commit

Permalink
Spec 2021: __typename is not valid at subscription root (ghostdogpr#1163
Browse files Browse the repository at this point in the history
)
  • Loading branch information
ghostdogpr authored and Fluxx committed Jan 27, 2022
1 parent e80f527 commit 0e70e31
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 26 deletions.
64 changes: 38 additions & 26 deletions core/src/main/scala/caliban/validation/Validator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -673,33 +673,45 @@ object Validator {
} else IO.succeed(fragmentMap.updated(fragment.name, fragment))
}

private def validateSubscriptionOperation(context: Context): IO[ValidationError, Unit] =
IO.fromOption(
private def validateSubscriptionOperation(context: Context): IO[ValidationError, Unit] = {
val error = {
for {
t <- context.rootType.subscriptionType
op <- context.operations
.filter(_.operationType == OperationType.Subscription)
.find(op =>
F(
op.selectionSet,
context.fragments,
Map.empty[String, InputValue],
List.empty[VariableDefinition],
t,
SourceMapper.empty,
Nil,
context.rootType
).fields.length > 1
)
} yield op
).map { op =>
val subscription = op.name.fold("")(n => s"'$n'")
ValidationError(
s"Subscription $subscription has more than one root field.",
"Subscription operations must have exactly one root field."
)
}.flip
.unit
t <- context.rootType.subscriptionType
op <- context.operations.find(_.operationType == OperationType.Subscription)
field = F(
op.selectionSet,
context.fragments,
Map.empty[String, InputValue],
List.empty[VariableDefinition],
t,
SourceMapper.empty,
Nil,
context.rootType
)
subscription = op.name.fold("")(n => s"'$n'")
error <- field.fields match {
case Nil => None
case head :: Nil =>
if (head.name == "__typename")
Some(
ValidationError(
s"Subscription $subscription has a field named '__typename'.",
"The root field of a subscription operation must not be an introspection field."
)
)
else None
case _ =>
Some(
ValidationError(
s"Subscription $subscription has more than one root field.",
"Subscription operations must have exactly one root field."
)
)
}
} yield error
}
IO.fromOption(error).flip.unit
}

private def validateFragmentType(name: Option[String], targetType: __Type): IO[ValidationError, Unit] =
targetType.kind match {
Expand Down
7 changes: 7 additions & 0 deletions core/src/test/scala/caliban/validation/ValidationSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ object ValidationSpec extends DefaultRunnableSpec {
}""")
check(query, "Subscription 's' has more than one root field.")
},
testM("subscription doesn't have a __typename field") {
val query = gqldoc("""
subscription s {
__typename
}""")
check(query, "Subscription 's' has a field named '__typename'.")
},
testM("invalid field") {
val query = gqldoc("""
{
Expand Down

0 comments on commit 0e70e31

Please sign in to comment.