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

federation 2.8 support #409

Merged
merged 4 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -34,6 +34,7 @@ public final class Federation {
public static final String FEDERATION_SPEC_V2_5 = "https://specs.apollo.dev/federation/v2.5";
public static final String FEDERATION_SPEC_V2_6 = "https://specs.apollo.dev/federation/v2.6";
public static final String FEDERATION_SPEC_V2_7 = "https://specs.apollo.dev/federation/v2.7";
public static final String FEDERATION_SPEC_V2_8 = "https://specs.apollo.dev/federation/v2.8";

private static final SchemaGenerator.Options defaultGeneratorOptions =
SchemaGenerator.Options.defaultOptions();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import static com.apollographql.federation.graphqljava.Federation.FEDERATION_SPEC_V2_5;
import static com.apollographql.federation.graphqljava.Federation.FEDERATION_SPEC_V2_6;
import static com.apollographql.federation.graphqljava.Federation.FEDERATION_SPEC_V2_7;
import static com.apollographql.federation.graphqljava.Federation.FEDERATION_SPEC_V2_8;
import static graphql.introspection.Introspection.DirectiveLocation.FIELD_DEFINITION;
import static graphql.introspection.Introspection.DirectiveLocation.INTERFACE;
import static graphql.introspection.Introspection.DirectiveLocation.OBJECT;
Expand Down Expand Up @@ -229,6 +230,8 @@ public static List<SDLNamedDefinition> loadFederationSpecDefinitions(String fede
return loadFed2Definitions("definitions_fed2_6.graphqls");
case FEDERATION_SPEC_V2_7:
return loadFed2Definitions("definitions_fed2_7.graphqls");
case FEDERATION_SPEC_V2_8:
return loadFed2Definitions("definitions_fed2_8.graphqls");
default:
throw new UnsupportedFederationVersionException(federationSpec);
}
Expand Down
117 changes: 117 additions & 0 deletions graphql-java-support/src/main/resources/definitions_fed2_8.graphqls
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#
# https://specs.apollo.dev/federation/v2.0/federation-v2.0.graphql
#

directive @key(fields: FieldSet!, resolvable: Boolean = true) repeatable on OBJECT | INTERFACE
directive @requires(fields: FieldSet!) on FIELD_DEFINITION
directive @provides(fields: FieldSet!) on FIELD_DEFINITION
directive @external on OBJECT | FIELD_DEFINITION
directive @extends on OBJECT | INTERFACE
directive @inaccessible on
| FIELD_DEFINITION
| OBJECT
| INTERFACE
| UNION
| ENUM
| ENUM_VALUE
| SCALAR
| INPUT_OBJECT
| INPUT_FIELD_DEFINITION
| ARGUMENT_DEFINITION
directive @tag(name: String!) repeatable on
| FIELD_DEFINITION
| INTERFACE
| OBJECT
| UNION
| ARGUMENT_DEFINITION
| SCALAR
| ENUM
| ENUM_VALUE
| INPUT_OBJECT
| INPUT_FIELD_DEFINITION
scalar FieldSet

#
# https://specs.apollo.dev/link/v1.0/link-v1.0.graphql
#

directive @link(
url: String!,
as: String,
import: [Import],
for: Purpose)
repeatable on SCHEMA

scalar Import

enum Purpose {
SECURITY
EXECUTION
}

#
# federation-v2.1
#

directive @composeDirective(name: String!) repeatable on SCHEMA

#
# federation-v2.2
#

directive @shareable repeatable on FIELD_DEFINITION | OBJECT

#
# federation-v2.3
#

directive @interfaceObject on OBJECT

#
# federation-v2.5
#

directive @authenticated on
ENUM
| FIELD_DEFINITION
| INTERFACE
| OBJECT
| SCALAR

directive @requiresScopes(scopes: [[Scope!]!]!) on
ENUM
| FIELD_DEFINITION
| INTERFACE
| OBJECT
| SCALAR

scalar Scope

#
# federation-v2.6
#

directive @policy(policies: [[Policy!]!]!) on
ENUM
| FIELD_DEFINITION
| INTERFACE
| OBJECT
| SCALAR

scalar Policy

#
# federation-v2.7
#

directive @override(from: String!, label: String) on FIELD_DEFINITION

#
# federation-v2.8
#

scalar ContextFieldValue

directive @context(name: String!) repeatable on INTERFACE | OBJECT | UNION

directive @fromContext(field: ContextFieldValue) on ARGUMENT_DEFINITION
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,11 @@ public void verifyFederationV2Transformation_policy() {
verifyFederationTransformation("schemas/policy/schema.graphql");
}

@Test
public void verifyFederationV2Transformation_context() {
verifyFederationTransformation("schemas/context/schema.graphql");
}

@Test
public void
verifyFederationV2Transformation_requiresScopesFromUnsupportedVersion_throwsException() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
extend schema @link(url: "https://specs.apollo.dev/federation/v2.8", import: ["@key", "@context", "@fromContext"])

type Product @key(fields: "id") @context(name: "product") {
id: ID!
name: String!
child: Child!
}

type Child @key(fields: "id") {
id: ID!
details(productName: String @fromContext(field: "$product { name }")): String!
}

type Query {
product(id: ID!): Product
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
schema @link(import : ["@key", "@context", "@fromContext"], url : "https://specs.apollo.dev/federation/v2.8"){
query: Query
}

directive @context(name: String!) repeatable on OBJECT | INTERFACE | UNION

directive @federation__authenticated on SCALAR | OBJECT | FIELD_DEFINITION | INTERFACE | ENUM

directive @federation__composeDirective(name: String!) repeatable on SCHEMA

directive @federation__extends on OBJECT | INTERFACE

directive @federation__external on OBJECT | FIELD_DEFINITION

directive @federation__interfaceObject on OBJECT

directive @federation__override(from: String!, label: String) on FIELD_DEFINITION

directive @federation__policy(policies: [[federation__Policy!]!]!) on SCALAR | OBJECT | FIELD_DEFINITION | INTERFACE | ENUM

directive @federation__provides(fields: federation__FieldSet!) on FIELD_DEFINITION

directive @federation__requires(fields: federation__FieldSet!) on FIELD_DEFINITION

directive @federation__requiresScopes(scopes: [[federation__Scope!]!]!) on SCALAR | OBJECT | FIELD_DEFINITION | INTERFACE | ENUM

directive @federation__shareable repeatable on OBJECT | FIELD_DEFINITION

directive @fromContext(field: federation__ContextFieldValue) on ARGUMENT_DEFINITION

directive @inaccessible on SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION

directive @key(fields: federation__FieldSet!, resolvable: Boolean = true) repeatable on OBJECT | INTERFACE

directive @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA

directive @tag(name: String!) repeatable on SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION

union _Entity = Child | Product

type Child @key(fields : "id", resolvable : true) {
details(productName: String @fromContext(field : "$product { name }")): String!
id: ID!
}

type Product @context(name : "product") @key(fields : "id", resolvable : true) {
child: Child!
id: ID!
name: String!
}

type Query {
_entities(representations: [_Any!]!): [_Entity]!
_service: _Service!
product(id: ID!): Product
}

type _Service {
sdl: String!
}

enum link__Purpose {
EXECUTION
SECURITY
}

scalar _Any

scalar federation__ContextFieldValue

scalar federation__FieldSet

scalar federation__Policy

scalar federation__Scope

scalar link__Import
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
schema @link(import : ["@key", "@context", "@fromContext"], url : "https://specs.apollo.dev/federation/v2.8"){
query: Query
}

directive @context(name: String!) repeatable on OBJECT | INTERFACE | UNION

"Marks the field, argument, input field or enum value as deprecated"
directive @deprecated(
"The reason for the deprecation"
reason: String = "No longer supported"
) on FIELD_DEFINITION | ARGUMENT_DEFINITION | ENUM_VALUE | INPUT_FIELD_DEFINITION

directive @federation__authenticated on SCALAR | OBJECT | FIELD_DEFINITION | INTERFACE | ENUM

directive @federation__composeDirective(name: String!) repeatable on SCHEMA

directive @federation__extends on OBJECT | INTERFACE

directive @federation__external on OBJECT | FIELD_DEFINITION

directive @federation__interfaceObject on OBJECT

directive @federation__override(from: String!, label: String) on FIELD_DEFINITION

directive @federation__policy(policies: [[federation__Policy!]!]!) on SCALAR | OBJECT | FIELD_DEFINITION | INTERFACE | ENUM

directive @federation__provides(fields: federation__FieldSet!) on FIELD_DEFINITION

directive @federation__requires(fields: federation__FieldSet!) on FIELD_DEFINITION

directive @federation__requiresScopes(scopes: [[federation__Scope!]!]!) on SCALAR | OBJECT | FIELD_DEFINITION | INTERFACE | ENUM

directive @federation__shareable repeatable on OBJECT | FIELD_DEFINITION

directive @fromContext(field: federation__ContextFieldValue) on ARGUMENT_DEFINITION

directive @inaccessible on SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION

"Directs the executor to include this field or fragment only when the `if` argument is true"
directive @include(
"Included when true."
if: Boolean!
) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT

directive @key(fields: federation__FieldSet!, resolvable: Boolean = true) repeatable on OBJECT | INTERFACE

directive @link(as: String, for: link__Purpose, import: [link__Import], url: String!) repeatable on SCHEMA

"Indicates an Input Object is a OneOf Input Object."
directive @oneOf on INPUT_OBJECT

"Directs the executor to skip this field or fragment when the `if` argument is true."
directive @skip(
"Skipped when true."
if: Boolean!
) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT

"Exposes a URL that specifies the behaviour of this scalar."
directive @specifiedBy(
"The URL that specifies the behaviour of this scalar."
url: String!
) on SCALAR

directive @tag(name: String!) repeatable on SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION

union _Entity = Child | Product

type Child @key(fields : "id", resolvable : true) {
details(productName: String @fromContext(field : "$product { name }")): String!
id: ID!
}

type Product @context(name : "product") @key(fields : "id", resolvable : true) {
child: Child!
id: ID!
name: String!
}

type Query {
_entities(representations: [_Any!]!): [_Entity]!
_service: _Service!
product(id: ID!): Product
}

type _Service {
sdl: String!
}

enum link__Purpose {
EXECUTION
SECURITY
}

scalar _Any

scalar federation__ContextFieldValue

scalar federation__FieldSet

scalar federation__Policy

scalar federation__Scope

scalar link__Import