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 1 commit
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
Next Next commit
Surface schema description when instantiating GraphQLSchema.
  • Loading branch information
Tom Groves committed Oct 28, 2021
commit 5ee79994adb5ad5fe9926ec870ad0337e9ef5de4
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"
const val DEFAULT_DESCRIPTION = "A GraphQL schema provides a root type for each kind of operation."

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
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ internal class SchemaClassScanner(
val query = createRootType("query", queryDefinition, queryName, true, queryResolvers, GraphQLQueryResolver::class.java, queryResolverInfo)
val mutation = createRootType("mutation", mutationDefinition, mutationName, rootInfo.isMutationRequired(), mutationResolvers, GraphQLMutationResolver::class.java, mutationResolverInfo)
val subscription = createRootType("subscription", subscriptionDefinition, subscriptionName, rootInfo.isSubscriptionRequired(), subscriptionResolvers, GraphQLSubscriptionResolver::class.java, subscriptionResolverInfo)
val schemaDescription = rootInfo.getDescription()

private fun createRootType(name: String, type: TypeDefinition<*>?, typeName: String, required: Boolean, resolvers: List<GraphQLRootResolver>, resolverInterface: Class<*>, resolverInfo: RootResolverInfo): RootType? {
if (type == 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
26 changes: 26 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,32 @@ class SchemaParserTest {
assertEquals(schema.queryType.getFieldDefinition("empty").description, "")
}

@Test
fun `parser should include schema descriptions`() {
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")
}

enum class EnumType {
TEST
}
Expand Down