Skip to content

Schema introspection description #596

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 19, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/main/kotlin/graphql/kickstart/tools/RootTypeInfo.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package graphql.kickstart.tools

import graphql.language.Description
import graphql.language.SchemaDefinition
import graphql.language.TypeName

Expand All @@ -9,25 +10,29 @@ import graphql.language.TypeName
internal class RootTypeInfo private constructor(
private val queryType: TypeName?,
private val mutationType: TypeName?,
private val subscriptionType: TypeName?
private val subscriptionType: TypeName?,
private val description: Description?
) {
companion object {
const val DEFAULT_QUERY_NAME = "Query"
const val DEFAULT_MUTATION_NAME = "Mutation"
const val DEFAULT_SUBSCRIPTION_NAME = "Subscription"
val DEFAULT_DESCRIPTION: String? = null // According to the GraphQL Specification description should be a string or `null`

fun fromSchemaDefinitions(definitions: List<SchemaDefinition>): RootTypeInfo {
val queryType = definitions.lastOrNull()?.operationTypeDefinitions?.find { it.name == "query" }?.typeName
val mutationType = definitions.lastOrNull()?.operationTypeDefinitions?.find { it.name == "mutation" }?.typeName
val subscriptionType = definitions.lastOrNull()?.operationTypeDefinitions?.find { it.name == "subscription" }?.typeName
val description = definitions.lastOrNull()?.description

return RootTypeInfo(queryType, mutationType, subscriptionType)
return RootTypeInfo(queryType, mutationType, subscriptionType, description)
}
}

fun getQueryName() = queryType?.name ?: DEFAULT_QUERY_NAME
fun getMutationName() = mutationType?.name ?: DEFAULT_MUTATION_NAME
fun getSubscriptionName() = subscriptionType?.name ?: DEFAULT_SUBSCRIPTION_NAME
fun getDescription() = description?.content ?: DEFAULT_DESCRIPTION

fun isMutationRequired() = mutationType != null
fun isSubscriptionRequired() = subscriptionType != null
Expand Down
4 changes: 3 additions & 1 deletion src/main/kotlin/graphql/kickstart/tools/SchemaObjects.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ data class SchemaObjects(
val mutation: GraphQLObjectType?,
val subscription: GraphQLObjectType?,
val dictionary: Set<GraphQLType>,
val codeRegistryBuilder: GraphQLCodeRegistry.Builder
val codeRegistryBuilder: GraphQLCodeRegistry.Builder,
val description: String?
) {
/**
* Makes a GraphQLSchema with query, mutation and subscription.
*/
fun toSchema(): GraphQLSchema {
return GraphQLSchema.newSchema()
.description(description)
.query(query)
.mutation(mutation)
.subscription(subscription)
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ class SchemaParser internal constructor(
val additionalObjects = objects.filter { o -> o != query && o != subscription && o != mutation }

val types = (additionalObjects.toSet() as Set<GraphQLType>) + inputObjects + enums + interfaces + unions
return SchemaObjects(query, mutation, subscription, types, codeRegistryBuilder)
return SchemaObjects(query, mutation, subscription, types, codeRegistryBuilder, rootInfo.getDescription())
}

/**
Expand Down
51 changes: 51 additions & 0 deletions src/test/kotlin/graphql/kickstart/tools/SchemaParserTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,57 @@ class SchemaParserTest {
assertEquals(schema.queryType.getFieldDefinition("empty").description, "")
}

@Test
fun `parser should include schema descriptions when declared`() {
val schema = SchemaParser.newParser()
.schemaString(
"""
"This is a schema level description"
schema {
query: SubstituteQuery
}

type SubstituteQuery {
description: String
comment: String
omitted: String
both: String
empty: String
}
""")
.resolvers(object : GraphQLQueryResolver {})
.options(SchemaParserOptions.newOptions().allowUnimplementedResolvers(true).build())
.build()
.makeExecutableSchema()

assertEquals(schema.description, "This is a schema level description")
}

@Test
fun `parser should return null schema description when not declared`() {
val schema = SchemaParser.newParser()
.schemaString(
"""
schema {
query: SubstituteQuery
}

type SubstituteQuery {
description: String
comment: String
omitted: String
both: String
empty: String
}
""")
.resolvers(object : GraphQLQueryResolver {})
.options(SchemaParserOptions.newOptions().allowUnimplementedResolvers(true).build())
.build()
.makeExecutableSchema()

assertNull(schema.description)
}

enum class EnumType {
TEST
}
Expand Down