Skip to content
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

fix: willAddGraphQLTypeToSchema needs annotations from field #1437

Merged
merged 4 commits into from
May 4, 2022
Merged
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ internal fun List<Annotation>.getUnionAnnotation(): GraphQLUnion? = this.filterI

internal fun List<Annotation>.getCustomUnionClassWithMetaUnionAnnotation(): KClass<*>? = this.firstOrNull { it.getMetaUnionAnnotation() != null }?.annotationClass

private fun Annotation.getMetaUnionAnnotation(): GraphQLUnion? = this.annotationClass.annotations.filterIsInstance(GraphQLUnion::class.java).firstOrNull()
internal fun Annotation.getMetaUnionAnnotation(): GraphQLUnion? = this.annotationClass.annotations.filterIsInstance(GraphQLUnion::class.java).firstOrNull()

internal fun List<Annotation>.getCustomTypeAnnotation(): GraphQLType? = this.filterIsInstance(GraphQLType::class.java).firstOrNull()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import com.expediagroup.graphql.generator.extensions.unwrapType
import com.expediagroup.graphql.generator.internal.extensions.getCustomTypeAnnotation
import com.expediagroup.graphql.generator.internal.extensions.getCustomUnionClassWithMetaUnionAnnotation
import com.expediagroup.graphql.generator.internal.extensions.getKClass
import com.expediagroup.graphql.generator.internal.extensions.getMetaUnionAnnotation
import com.expediagroup.graphql.generator.internal.extensions.getUnionAnnotation
import com.expediagroup.graphql.generator.internal.extensions.isAnnotation
import com.expediagroup.graphql.generator.internal.extensions.isEnum
Expand All @@ -32,6 +33,7 @@ import graphql.schema.GraphQLType
import graphql.schema.GraphQLTypeReference
import kotlin.reflect.KClass
import kotlin.reflect.KType
import kotlin.reflect.full.createType

/**
* Return a basic GraphQL type given all the information about the kotlin type.
Expand Down Expand Up @@ -63,7 +65,15 @@ private fun objectFromReflection(generator: SchemaGenerator, type: KType, typeIn

return generator.cache.buildIfNotUnderConstruction(kClass, typeInfo) {
val graphQLType = getGraphQLType(generator, kClass, type, typeInfo)
generator.config.hooks.willAddGraphQLTypeToSchema(type, graphQLType)

/*
* For a field using the meta union annotation, the `type` is `Any`, but we need to pass the annotation with the meta union annotation as the type
* since that is really the type generated from reflection and has any potential directives on it needed by the hook
*/
val metaUnion: Annotation? = typeInfo.fieldAnnotations.firstOrNull { it.getMetaUnionAnnotation() != null }
bherrmann2 marked this conversation as resolved.
Show resolved Hide resolved
val resolvedType = if (kClass.isInstance(Any::class) && metaUnion != null) metaUnion.annotationClass.createType() else type
bherrmann2 marked this conversation as resolved.
Show resolved Hide resolved

generator.config.hooks.willAddGraphQLTypeToSchema(resolvedType, graphQLType)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ import com.expediagroup.graphql.generator.SchemaGenerator
import com.expediagroup.graphql.generator.SchemaGeneratorConfig
import com.expediagroup.graphql.generator.TopLevelObject
import com.expediagroup.graphql.generator.annotations.GraphQLIgnore
import com.expediagroup.graphql.generator.annotations.GraphQLUnion
import com.expediagroup.graphql.generator.exceptions.EmptyInputObjectTypeException
import com.expediagroup.graphql.generator.exceptions.EmptyInterfaceTypeException
import com.expediagroup.graphql.generator.exceptions.EmptyObjectTypeException
import com.expediagroup.graphql.generator.extensions.deepName
import com.expediagroup.graphql.generator.getTestSchemaConfigWithHooks
import com.expediagroup.graphql.generator.internal.extensions.getKClass
import com.expediagroup.graphql.generator.internal.extensions.getSimpleName
import com.expediagroup.graphql.generator.test.utils.graphqlUUIDType
import com.expediagroup.graphql.generator.testSchemaConfig
Expand All @@ -36,6 +38,7 @@ import graphql.schema.GraphQLObjectType
import graphql.schema.GraphQLScalarType
import graphql.schema.GraphQLSchema
import graphql.schema.GraphQLType
import graphql.schema.GraphQLUnionType
import graphql.schema.validation.InvalidSchemaException
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.reactive.asPublisher
Expand Down Expand Up @@ -221,19 +224,25 @@ class SchemaGeneratorHooksTest {
override fun willAddGraphQLTypeToSchema(type: KType, generatedType: GraphQLType): GraphQLType {
hookCalled = true
return when {
generatedType is GraphQLObjectType && generatedType.name == "SomeData" -> GraphQLObjectType.newObject(generatedType).description("My custom description").build()
generatedType is GraphQLInterfaceType && generatedType.name == "RandomData" ->
generatedType is GraphQLObjectType && generatedType.name == "SomeData" && type.getKClass() == SomeData::class ->
GraphQLObjectType.newObject(generatedType).description("My custom description").build()
generatedType is GraphQLInterfaceType && generatedType.name == "RandomData" && type.getKClass() == RandomData::class ->
GraphQLInterfaceType.newInterface(generatedType).description("My custom interface description").build()
generatedType is GraphQLUnionType && generatedType.name == "MyMetaUnion" && type.getKClass() == MyMetaUnion::class ->
GraphQLUnionType.newUnionType(generatedType).description("My meta union description").build()
generatedType is GraphQLUnionType && generatedType.name == "MyAdditionalMetaUnion" && type.getKClass() == MyAdditionalMetaUnion::class ->
GraphQLUnionType.newUnionType(generatedType).description("My additional meta union description").build()
else -> generatedType
}
}
}

val hooks = MockSchemaGeneratorHooks()
val schema = toSchema(
queries = listOf(TopLevelObject(TestQuery())),
config = getTestSchemaConfigWithHooks(hooks)
)
val generator = SchemaGenerator(getTestSchemaConfigWithHooks(hooks))
val schema = generator.use {
it.generateSchema(queries = listOf(TopLevelObject(TestQuery())), additionalTypes = setOf(MyAdditionalMetaUnion::class.createType()))
}

assertTrue(hooks.hookCalled)

val type = schema.getObjectType("SomeData")
Expand All @@ -243,6 +252,14 @@ class SchemaGeneratorHooksTest {
val interfaceType = schema.getType("RandomData") as? GraphQLInterfaceType
assertNotNull(interfaceType)
assertEquals(expected = "My custom interface description", actual = interfaceType.description)

val metaUnionType = schema.getType("MyMetaUnion") as? GraphQLUnionType
assertNotNull(metaUnionType)
assertEquals(expected = "My meta union description", actual = metaUnionType.description)

val additionalMetaUnionType = schema.getType("MyAdditionalMetaUnion") as? GraphQLUnionType
assertNotNull(additionalMetaUnionType)
assertEquals(expected = "My additional meta union description", actual = additionalMetaUnionType.description)
}

@Test
Expand Down Expand Up @@ -346,8 +363,16 @@ class SchemaGeneratorHooksTest {

class TestQuery {
fun query(): SomeData = SomeData("someData", 0)
@MyMetaUnion
fun unionQuery(): Any = SomeData("someData", 0)
}

@GraphQLUnion(name = "MyMetaUnion", possibleTypes = [SomeData::class])
annotation class MyMetaUnion

@GraphQLUnion(name = "MyAdditionalMetaUnion", possibleTypes = [SomeData::class])
annotation class MyAdditionalMetaUnion

class TestSubscription {
fun subscription(): Publisher<SomeData> = flowOf(SomeData("someData", 0)).asPublisher()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ class AnnotationExtensionsTest {
assertNull(WithAnnotations::class.findMemberProperty("id")?.annotations?.getUnionAnnotation())
@Suppress("DEPRECATION")
assertNull(WithAnnotations::class.findMemberProperty("id")?.annotations?.getCustomUnionClassWithMetaUnionAnnotation())
@Suppress("DEPRECATION")
assertNotNull(WithAnnotations::class.findMemberProperty("metaUnion")?.annotations?.firstOrNull { it is MetaUnion }?.getMetaUnionAnnotation())
@Suppress("DEPRECATION")
assertNull(WithAnnotations::class.findMemberProperty("union")?.annotations?.firstOrNull { it is GraphQLUnion }?.getMetaUnionAnnotation())
}

private fun KClass<*>.findMemberProperty(name: String) = this.declaredMemberProperties.find { it.name == name }
Expand Down