Skip to content

Commit 748529f

Browse files
dariuszkucsmyrick
authored andcommitted
[federation] fix: SDL should be generated for non-federated schemas (#417)
Federated GraphQL gateway can contain number of services that are not exposing any of their types as federated types (i.e. without exposing any of them using @key directives). We were incorrectly generating SDL only if there were some federated types in the generated schema. Fix is to always generated the SDL.
1 parent 60253be commit 748529f

File tree

2 files changed

+64
-19
lines changed

2 files changed

+64
-19
lines changed

graphql-kotlin-federation/src/main/kotlin/com/expediagroup/graphql/federation/FederatedSchemaGeneratorHooks.kt

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,25 @@ open class FederatedSchemaGeneratorHooks(private val federatedTypeRegistry: Fede
6969
.field(SERVICE_FIELD_DEFINITION)
7070
.withDirective(extendsDirectiveType)
7171

72+
/**
73+
* SDL returned by _service query should NOT contain
74+
* - default schema definition
75+
* - empty Query type
76+
* - any directive definitions
77+
* - any custom directives
78+
* - new federated scalars
79+
*/
80+
val sdl = originalSchema.print(includeDefaultSchemaDefinition = false)
81+
/**
82+
* TODO: this can be simplified once this is solved: apollographql/apollo-server#3334
83+
*/
84+
.replace(directiveDefinitionRegex, "")
85+
.replace(scalarDefinitionRegex, "")
86+
.replace(emptyQueryRegex, "")
87+
.replace(customDirectivesRegex, "")
88+
.trim()
89+
federatedCodeRegistry.dataFetcher(FieldCoordinates.coordinates(originalQuery.name, SERVICE_FIELD_DEFINITION.name), DataFetcher { _Service(sdl) })
90+
7291
val entityTypeNames = originalSchema.allTypesAsList
7392
.asSequence()
7493
.filterIsInstance<GraphQLObjectType>()
@@ -81,25 +100,6 @@ open class FederatedSchemaGeneratorHooks(private val federatedTypeRegistry: Fede
81100
val entityField = generateEntityFieldDefinition(entityTypeNames)
82101
federatedQuery.field(entityField)
83102

84-
/**
85-
* SDL returned by _service query should NOT contain
86-
* - default schema definition
87-
* - empty Query type
88-
* - any directive definitions
89-
* - any custom directives
90-
* - new federated scalars
91-
*/
92-
val sdl = originalSchema.print(includeDefaultSchemaDefinition = false)
93-
/**
94-
* TODO: this can be simplified once this is solved: apollographql/apollo-server#3334
95-
*/
96-
.replace(directiveDefinitionRegex, "")
97-
.replace(scalarDefinitionRegex, "")
98-
.replace(emptyQueryRegex, "")
99-
.replace(customDirectivesRegex, "")
100-
.trim()
101-
102-
federatedCodeRegistry.dataFetcher(FieldCoordinates.coordinates(originalQuery.name, SERVICE_FIELD_DEFINITION.name), DataFetcher { _Service(sdl) })
103103
federatedCodeRegistry.dataFetcher(FieldCoordinates.coordinates(originalQuery.name, entityField.name), EntityResolver(federatedTypeRegistry))
104104
federatedCodeRegistry.typeResolver("_Entity") { env: TypeResolutionEnvironment -> env.schema.getObjectType(env.getObjectName()) }
105105
federatedSchema.additionalType(ANY_SCALAR_TYPE)

graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/federation/execution/ServiceQueryResolverTest.kt

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@
1616

1717
package com.expediagroup.graphql.federation.execution
1818

19+
import com.expediagroup.graphql.TopLevelObject
1920
import com.expediagroup.graphql.federation.FederatedSchemaGeneratorConfig
2021
import com.expediagroup.graphql.federation.FederatedSchemaGeneratorHooks
2122
import com.expediagroup.graphql.federation.toFederatedSchema
2223
import graphql.ExecutionInput
2324
import graphql.GraphQL
2425
import org.junit.jupiter.api.Test
26+
import test.data.queries.simple.NestedQuery
27+
import test.data.queries.simple.SimpleQuery
2528
import kotlin.test.assertEquals
2629
import kotlin.test.assertNotNull
2730

@@ -51,6 +54,19 @@ type User @extends @key(fields : "userId") {
5154
userId: Int! @external
5255
}"""
5356

57+
const val BASE_SERVICE_SDL = """
58+
type Query {
59+
getSimpleNestedObject: [SelfReferenceObject]!
60+
hello(name: String!): String!
61+
}
62+
63+
type SelfReferenceObject {
64+
description: String
65+
id: Int!
66+
nextObject: [SelfReferenceObject]!
67+
}
68+
"""
69+
5470
class ServiceQueryResolverTest {
5571

5672
@Test
@@ -81,4 +97,33 @@ class ServiceQueryResolverTest {
8197
}
8298
}
8399
}
100+
101+
@Test
102+
fun `verify can retrieve SDL using _service query for non-federated schemas`() {
103+
val config = FederatedSchemaGeneratorConfig(
104+
supportedPackages = listOf("test.data.queries.simple"),
105+
hooks = FederatedSchemaGeneratorHooks(FederatedTypeRegistry())
106+
)
107+
108+
val schema = toFederatedSchema(config = config, queries = listOf(TopLevelObject(SimpleQuery()), TopLevelObject(NestedQuery())))
109+
val query = """
110+
query sdlQuery {
111+
_service {
112+
sdl
113+
}
114+
}
115+
""".trimIndent()
116+
val executionInput = ExecutionInput.newExecutionInput()
117+
.query(query)
118+
.build()
119+
val graphQL = GraphQL.newGraphQL(schema).build()
120+
val result = graphQL.executeAsync(executionInput).get().toSpecification()
121+
122+
assertNotNull(result["data"] as? Map<*, *>) { data ->
123+
assertNotNull(data["_service"] as? Map<*, *>) { queryResult ->
124+
val sdl = queryResult["sdl"] as? String
125+
assertEquals(BASE_SERVICE_SDL.trim(), sdl)
126+
}
127+
}
128+
}
84129
}

0 commit comments

Comments
 (0)