Skip to content

Commit

Permalink
[federation] use federation-jvm ServiceSDLPrinter (#1546)
Browse files Browse the repository at this point in the history
Updated `FederatedSchemaGeneratorHooks` to use `ServiceSDLPrinter` provided by the `federation-jvm` in favor of our custom printer logic.
  • Loading branch information
dariuszkuc authored Sep 12, 2022
1 parent 095b056 commit c65f2a1
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@

package com.expediagroup.graphql.generator.federation

import com.apollographql.federation.graphqljava.printer.ServiceSDLPrinter.generateServiceSDL
import com.apollographql.federation.graphqljava.printer.ServiceSDLPrinter.generateServiceSDLV2
import com.expediagroup.graphql.generator.annotations.GraphQLName
import com.expediagroup.graphql.generator.directives.DEPRECATED_DIRECTIVE_NAME
import com.expediagroup.graphql.generator.directives.DirectiveMetaInformation
import com.expediagroup.graphql.generator.extensions.print
import com.expediagroup.graphql.generator.federation.directives.EXTENDS_DIRECTIVE_TYPE
import com.expediagroup.graphql.generator.federation.directives.EXTERNAL_DIRECTIVE_TYPE
import com.expediagroup.graphql.generator.federation.directives.FEDERATION_SPEC_URL
Expand Down Expand Up @@ -61,18 +61,13 @@ import graphql.schema.GraphQLDirective
import graphql.schema.GraphQLObjectType
import graphql.schema.GraphQLSchema
import graphql.schema.GraphQLType
import java.util.function.Predicate
import kotlin.reflect.KType
import kotlin.reflect.full.findAnnotation

/**
* Hooks for generating federated GraphQL schema.
*/
open class FederatedSchemaGeneratorHooks(private val resolvers: List<FederatedTypeResolver<*>>, private val optInFederationV2: Boolean = false) : SchemaGeneratorHooks {
private val scalarDefinitionRegex = "(^\".+\"$[\\r\\n])?^scalar (_FieldSet|_Any)$[\\r\\n]*".toRegex(setOf(RegexOption.MULTILINE, RegexOption.IGNORE_CASE))
private val emptyQueryRegex = "^type Query @extends \\s*\\{\\s*}\\s*".toRegex(setOf(RegexOption.MULTILINE, RegexOption.IGNORE_CASE))
private val serviceFieldRegex = "\\s*_service: _Service!".toRegex(setOf(RegexOption.MULTILINE, RegexOption.IGNORE_CASE))
private val serviceTypeRegex = "^type _Service\\s*\\{\\s*sdl: String!\\s*}\\s*".toRegex(setOf(RegexOption.MULTILINE, RegexOption.IGNORE_CASE))
private val validator = FederatedSchemaValidator()

private val federationV2OnlyDirectiveNames: Set<String> = setOf(
Expand Down Expand Up @@ -206,17 +201,11 @@ open class FederatedSchemaGeneratorHooks(private val resolvers: List<FederatedTy
* https://www.apollographql.com/docs/apollo-server/federation/federation-spec/#query_service
*/
private fun getFederatedServiceSdl(schema: GraphQLSchema): String {
val directivesToInclude: List<String> = federatedDirectiveList().map { it.name }.plus(DEPRECATED_DIRECTIVE_NAME)
val customDirectivePredicate: Predicate<String> = Predicate { directivesToInclude.contains(it) }
return schema.print(
includeDefaultSchemaDefinition = optInFederationV2,
includeDirectiveDefinitions = false,
includeDirectivesFilter = customDirectivePredicate
).replace(scalarDefinitionRegex, "")
.replace(serviceFieldRegex, "")
.replace(serviceTypeRegex, "")
.replace(emptyQueryRegex, "")
.trim()
return if (optInFederationV2) {
generateServiceSDLV2(schema)
} else {
generateServiceSDL(schema, false)
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ import kotlin.test.assertNotNull
// SDL is returned without _entity and _service queries
const val FEDERATED_SERVICE_SDL =
"""
schema {
query: Query
}
interface Product @extends @key(fields : "id") @key(fields : "upc") {
id: String! @external
reviews: [Review!]!
Expand All @@ -54,6 +58,8 @@ type Book implements Product @extends @key(fields : "id") @key(fields : "upc") {
weight: Float! @external
}
type Query @extends
type Review {
body: String!
content: String @deprecated(reason : "no longer supported, replace with use Review.body instead")
Expand All @@ -75,6 +81,10 @@ scalar CustomScalar"""

const val BASE_SERVICE_SDL =
"""
schema {
query: Query
}
type Query @extends {
getSimpleNestedObject: [SelfReferenceObject]!
hello(name: String!): String!
Expand All @@ -93,6 +103,23 @@ schema @link(url : "https://specs.apollo.dev/link/v1.0/") @link(import : ["exten
query: Query
}
directive @custom on SCHEMA | SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
"Marks target object as extending part of the federated schema"
directive @extends on OBJECT | INTERFACE
"Marks target field as external meaning it will be resolved by federated schema"
directive @external on FIELD_DEFINITION
"Space separated list of primary keys needed to access federated object"
directive @key(fields: _FieldSet!, resolvable: Boolean = true) repeatable on OBJECT | INTERFACE
"Specifies the base type field set that will be selectable by the gateway"
directive @provides(fields: _FieldSet!) on FIELD_DEFINITION
"Specifies required input field set from the base type for a resolver"
directive @requires(fields: _FieldSet!) on FIELD_DEFINITION
interface Product @extends @key(fields : "id", resolvable : true) @key(fields : "upc", resolvable : true) {
id: String! @external
reviews: [Review!]!
Expand All @@ -112,8 +139,12 @@ type CustomScalar {
value: String!
}
type Query @extends {
_service: _Service!
}
type Review {
body: String!
body: String! @custom
content: String @deprecated(reason : "no longer supported, replace with use Review.body instead")
customScalar: CustomScalar!
id: String!
Expand All @@ -123,6 +154,13 @@ type User @extends @key(fields : "userId", resolvable : true) {
name: String! @external
userId: Int! @external
}
type _Service {
sdl: String!
}
"Federation type representing set of fields"
scalar _FieldSet
"""

class ServiceQueryResolverTest {
Expand Down
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ kotlinxSerializationVersion = 1.3.2

androidPluginVersion = 7.1.2
classGraphVersion = 4.8.149
federationGraphQLVersion = 2.0.4
graphQLJavaVersion = 19.1
federationGraphQLVersion = 2.0.7
graphQLJavaVersion = 19.2
graphQLJavaDataLoaderVersion = 3.2.0
jacksonVersion = 2.13.3
# KotlinPoet v1.12.0+ requires Kotlin v1.7
Expand Down

0 comments on commit c65f2a1

Please sign in to comment.