Skip to content

Commit 8136a43

Browse files
author
Shane Myrick
authored
feat: new hook for modifying object types (#232)
Fixes #231 Adds a new hook that can be used to modify all the GraphQLTypes that get generated from reflection. This allows for runtime documentation or any other changes that may want to be made to types after they are fully generated
1 parent 625dafa commit 8136a43

File tree

3 files changed

+43
-6
lines changed

3 files changed

+43
-6
lines changed

src/main/kotlin/com/expedia/graphql/generator/TypeBuilder.kt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,12 @@ internal open class TypeBuilder constructor(protected val generator: SchemaGener
2323
val graphQLType = hookGraphQLType
2424
?: generator.scalarType(type, annotatedAsID)
2525
?: objectFromReflection(type, inputType)
26-
val typeWithNullityTakenIntoAccount = graphQLType.wrapInNonNull(type)
27-
config.hooks.didGenerateGraphQLType(type, typeWithNullityTakenIntoAccount)
28-
return typeWithNullityTakenIntoAccount
26+
27+
val typeWithNullability = graphQLType.wrapInNonNull(type)
28+
29+
config.hooks.didGenerateGraphQLType(type, typeWithNullability)
30+
31+
return typeWithNullability
2932
}
3033

3134
internal fun objectFromReflection(type: KType, inputType: Boolean): GraphQLType {
@@ -39,12 +42,14 @@ internal open class TypeBuilder constructor(protected val generator: SchemaGener
3942
val kClass = type.getKClass()
4043
val graphQLType = getGraphQLType(kClass, inputType, type)
4144

42-
if (graphQLType !is GraphQLTypeReference) {
43-
val kGraphQLType = KGraphQLType(kClass, graphQLType)
45+
val modifiedGraphQLType = config.hooks.willAddGraphQLTypeToSchema(type, graphQLType)
46+
47+
if (modifiedGraphQLType !is GraphQLTypeReference) {
48+
val kGraphQLType = KGraphQLType(kClass, modifiedGraphQLType)
4449
state.cache.put(cacheKey, kGraphQLType)
4550
}
4651

47-
return graphQLType
52+
return modifiedGraphQLType
4853
}
4954

5055
private fun getGraphQLType(kClass: KClass<*>, inputType: Boolean, type: KType): GraphQLType = when {

src/main/kotlin/com/expedia/graphql/hooks/SchemaGeneratorHooks.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ interface SchemaGeneratorHooks {
2828
@Suppress("Detekt.FunctionOnlyReturningConstant")
2929
fun willGenerateGraphQLType(type: KType): GraphQLType? = null
3030

31+
/**
32+
* Called after using reflection to generate the graphql object type but before returning it to the schema builder.
33+
* This allows for modifying the type info, like description or directives
34+
*/
35+
fun willAddGraphQLTypeToSchema(type: KType, generatedType: GraphQLType): GraphQLType = generatedType
36+
3137
/**
3238
* Called before resolving a KType to the GraphQL type.
3339
* This allows for a custom resolver on how to extract wrapped values, like in a CompletableFuture.

src/test/kotlin/com/expedia/graphql/hooks/SchemaGeneratorHooksTest.kt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,32 @@ class SchemaGeneratorHooksTest {
123123
assertEquals("SomeData!", hooks.lastSeenGeneratedType?.deepName)
124124
}
125125

126+
@Test
127+
fun `calls hook before adding type to schema`() {
128+
class MockSchemaGeneratorHooks : SchemaGeneratorHooks {
129+
var hookCalled = false
130+
131+
override fun willAddGraphQLTypeToSchema(type: KType, generatedType: GraphQLType): GraphQLType {
132+
hookCalled = true
133+
return when {
134+
generatedType is GraphQLObjectType && generatedType.name == "SomeData" -> GraphQLObjectType.Builder(generatedType).description("My custom description").build()
135+
else -> generatedType
136+
}
137+
}
138+
}
139+
140+
val hooks = MockSchemaGeneratorHooks()
141+
val schema = toSchema(
142+
queries = listOf(TopLevelObject(TestQuery())),
143+
config = getTestSchemaConfigWithHooks(hooks)
144+
)
145+
assertTrue(hooks.hookCalled)
146+
147+
val type = schema.getObjectType("SomeData")
148+
assertNotNull(type)
149+
assertEquals(expected = "My custom description", actual = type.description)
150+
}
151+
126152
@Test
127153
fun `calls hook before adding query to schema`() {
128154
class MockSchemaGeneratorHooks : SchemaGeneratorHooks {

0 commit comments

Comments
 (0)