Skip to content

Commit 2e07363

Browse files
authored
fix: fixed imports when both schema and extension are present (#258)
While introducing [Fed 2.1 support](#249) I added a validation to ensure only single federation `@link` import is present. That logic had a bug that if `schema` was present it never hit the else condition as `Optional` had a value in it (empty stream). Updated logic to correctly process both `schema` and its extensions. Resolves: #257
1 parent ef48c48 commit 2e07363

File tree

5 files changed

+97
-6
lines changed

5 files changed

+97
-6
lines changed

graphql-java-support/src/main/java/com/apollographql/federation/graphqljava/directives/LinkDirectiveProcessor.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,19 @@ private LinkDirectiveProcessor() {}
3838
*/
3939
public static @Nullable Stream<SDLNamedDefinition> loadFederationImportedDefinitions(
4040
TypeDefinitionRegistry typeDefinitionRegistry) {
41-
List<Directive> federationLinkDirectives =
41+
42+
Stream<Directive> schemaLinkDirectives =
4243
typeDefinitionRegistry
4344
.schemaDefinition()
4445
.map(LinkDirectiveProcessor::getFederationLinkDirectives)
45-
.orElseGet(
46-
() ->
47-
typeDefinitionRegistry.getSchemaExtensionDefinitions().stream()
48-
.flatMap(LinkDirectiveProcessor::getFederationLinkDirectives))
49-
.collect(Collectors.toList());
46+
.orElse(Stream.empty());
47+
48+
Stream<Directive> extensionLinkDirectives =
49+
typeDefinitionRegistry.getSchemaExtensionDefinitions().stream()
50+
.flatMap(LinkDirectiveProcessor::getFederationLinkDirectives);
51+
52+
List<Directive> federationLinkDirectives =
53+
Stream.concat(schemaLinkDirectives, extensionLinkDirectives).collect(Collectors.toList());
5054

5155
if (federationLinkDirectives.isEmpty()) {
5256
return null;

graphql-java-support/src/test/java/com/apollographql/federation/graphqljava/FederationTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,20 @@ public void verifyFederationV2Transformation_multipleFedLinks_throwsException()
235235
() -> Federation.transform(schemaSDL).fetchEntities(env -> null).build());
236236
}
237237

238+
@Test
239+
public void verifySchemaCanBeExtended() {
240+
verifyFederationTransformation("schemas/extendSchema.graphql", true);
241+
}
242+
243+
@Test
244+
public void
245+
verifyFederationV2Transformation_multipleFedLinksSchemaAndExtension_throwsException() {
246+
final String schemaSDL = FileUtils.readResource("schemas/multipleSchemaLinks.graphql");
247+
assertThrows(
248+
MultipleFederationLinksException.class,
249+
() -> Federation.transform(schemaSDL).fetchEntities(env -> null).build());
250+
}
251+
238252
private GraphQLSchema verifyFederationTransformation(
239253
String schemaFileName, boolean isFederationV2) {
240254
final RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring().build();
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key"])
2+
3+
schema {
4+
query: Query
5+
}
6+
7+
type Product @key(fields: "id") {
8+
id: ID!
9+
}
10+
11+
type Query {
12+
product(id: ID!): Product
13+
}
14+
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
schema @link(import : ["@key"], url : "https://specs.apollo.dev/federation/v2.0"){
2+
query: Query
3+
}
4+
5+
directive @federation__extends on OBJECT | INTERFACE
6+
7+
directive @federation__external on OBJECT | FIELD_DEFINITION
8+
9+
directive @federation__override(from: String!) on FIELD_DEFINITION
10+
11+
directive @federation__provides(fields: federation__FieldSet!) on FIELD_DEFINITION
12+
13+
directive @federation__requires(fields: federation__FieldSet!) on FIELD_DEFINITION
14+
15+
directive @federation__shareable on OBJECT | FIELD_DEFINITION
16+
17+
directive @inaccessible on SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
18+
19+
directive @key(fields: federation__FieldSet!, resolvable: Boolean = true) repeatable on OBJECT | INTERFACE
20+
21+
directive @link(as: String, import: [link__Import], url: String!) repeatable on SCHEMA
22+
23+
directive @tag(name: String!) repeatable on SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
24+
25+
union _Entity = Product
26+
27+
type Product @key(fields : "id", resolvable : true) {
28+
id: ID!
29+
}
30+
31+
type Query {
32+
_entities(representations: [_Any!]!): [_Entity]!
33+
_service: _Service!
34+
product(id: ID!): Product
35+
}
36+
37+
type _Service {
38+
sdl: String!
39+
}
40+
41+
scalar _Any
42+
43+
scalar federation__FieldSet
44+
45+
scalar link__Import
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key"])
2+
3+
schema @link(url: "https://specs.apollo.dev/federation/v2.1", import: ["@tag"]) {
4+
query: Query
5+
}
6+
7+
type Product @key(fields: "id") {
8+
id: ID!
9+
name: String! @tag(name: "example")
10+
}
11+
12+
type Query {
13+
product(id: ID!): Product
14+
}

0 commit comments

Comments
 (0)