diff --git a/compatibility/src/main/java/com/apollographql/federation/compatibility/GraphQLConfiguration.java b/compatibility/src/main/java/com/apollographql/federation/compatibility/GraphQLConfiguration.java index 29fcc6a0..60b045f0 100644 --- a/compatibility/src/main/java/com/apollographql/federation/compatibility/GraphQLConfiguration.java +++ b/compatibility/src/main/java/com/apollographql/federation/compatibility/GraphQLConfiguration.java @@ -1,6 +1,7 @@ package com.apollographql.federation.compatibility; import com.apollographql.federation.compatibility.model.DeprecatedProduct; +import com.apollographql.federation.compatibility.model.Inventory; import com.apollographql.federation.compatibility.model.Product; import com.apollographql.federation.compatibility.model.ProductResearch; import com.apollographql.federation.compatibility.model.User; @@ -17,42 +18,45 @@ @Configuration public class GraphQLConfiguration { - @Bean - public FederatedTracingInstrumentation federatedTracingInstrumentation() { - return new FederatedTracingInstrumentation(); - } + @Bean + public FederatedTracingInstrumentation federatedTracingInstrumentation() { + return new FederatedTracingInstrumentation(); + } - @Bean - public GraphQlSourceBuilderCustomizer federationTransform() { - return builder -> builder.schemaFactory((registry, wiring) -> - Federation.transform(registry, wiring) - .fetchEntities(env -> - env.>>getArgument(_Entity.argumentName).stream().map(reference -> { - final String typeName = (String)reference.get("__typename"); - return switch (typeName) { - case "DeprecatedProduct" -> DeprecatedProduct.resolveReference(reference); - case "Product" -> Product.resolveReference(reference); - case "ProductResearch" -> ProductResearch.resolveReference(reference); - case "User" -> User.resolveReference(reference); - default -> null; - }; - }).collect(Collectors.toList()) - ) - .resolveEntityType(env -> { - final Object src = env.getObject(); - if (src instanceof DeprecatedProduct) { - return env.getSchema().getObjectType("DeprecatedProduct"); - } else if (src instanceof Product) { - return env.getSchema().getObjectType("Product"); - } else if (src instanceof ProductResearch) { - return env.getSchema().getObjectType("ProductResearch"); - } else if (src instanceof User) { - return env.getSchema().getObjectType("User"); - } else { - return null; - } - }) - .build() - ); - } -} \ No newline at end of file + @Bean + public GraphQlSourceBuilderCustomizer federationTransform() { + return builder -> builder.schemaFactory((registry, wiring) -> + Federation.transform(registry, wiring) + .fetchEntities(env -> + env.>>getArgument(_Entity.argumentName).stream().map(reference -> { + final String typeName = (String) reference.get("__typename"); + return switch (typeName) { + case "DeprecatedProduct" -> DeprecatedProduct.resolveReference(reference); + case "Product" -> Product.resolveReference(reference); + case "ProductResearch" -> ProductResearch.resolveReference(reference); + case "User" -> User.resolveReference(reference); + case "Inventory" -> Inventory.resolveReference(reference); + default -> null; + }; + }).collect(Collectors.toList()) + ) + .resolveEntityType(env -> { + final Object src = env.getObject(); + if (src instanceof DeprecatedProduct) { + return env.getSchema().getObjectType("DeprecatedProduct"); + } else if (src instanceof Product) { + return env.getSchema().getObjectType("Product"); + } else if (src instanceof ProductResearch) { + return env.getSchema().getObjectType("ProductResearch"); + } else if (src instanceof User) { + return env.getSchema().getObjectType("User"); + } else if (src instanceof Inventory) { + return env.getSchema().getObjectType("Inventory"); + } else { + return null; + } + }) + .build() + ); + } +} diff --git a/compatibility/src/main/java/com/apollographql/federation/compatibility/model/Inventory.java b/compatibility/src/main/java/com/apollographql/federation/compatibility/model/Inventory.java new file mode 100644 index 00000000..7749f260 --- /dev/null +++ b/compatibility/src/main/java/com/apollographql/federation/compatibility/model/Inventory.java @@ -0,0 +1,34 @@ +package com.apollographql.federation.compatibility.model; + +import static com.apollographql.federation.compatibility.model.DeprecatedProduct.DEPRECATED_PRODUCT; + +import java.util.List; +import java.util.Map; +import org.jetbrains.annotations.NotNull; + +public class Inventory { + + private final String id; + private final List deprecatedProducts; + + public Inventory(String id) { + this.id = id; + this.deprecatedProducts = List.of(DEPRECATED_PRODUCT); + } + + public String getId() { + return id; + } + + public List getDeprecatedProducts() { + return deprecatedProducts; + } + + public static Inventory resolveReference(@NotNull Map reference) { + if (reference.get("id") instanceof String id && "apollo-oss".equals(id)) { + return new Inventory(id); + } + + return null; + } +} diff --git a/compatibility/src/main/resources/graphql/schema.graphqls b/compatibility/src/main/resources/graphql/schema.graphqls index 36dbc20f..34801d7c 100644 --- a/compatibility/src/main/resources/graphql/schema.graphqls +++ b/compatibility/src/main/resources/graphql/schema.graphqls @@ -1,56 +1,77 @@ extend schema -@link( - url: "https://specs.apollo.dev/federation/v2.0", - import: ["@extends", "@external", "@inaccessible", "@key", "@override", "@provides", "@requires", "@shareable", "@tag"] -) - -type Product @key(fields: "id") @key(fields: "sku package") @key(fields: "sku variation { id }") { - id: ID! - sku: String - package: String - variation: ProductVariation - dimensions: ProductDimension - createdBy: User @provides(fields: "totalProductsCreated") - notes: String @tag(name: "internal") - research: [ProductResearch!]! + @link( + url: "https://specs.apollo.dev/federation/v2.3", + import: [ + "@composeDirective", + "@extends", + "@external", + "@inaccessible", + "@interfaceObject", + "@key", + "@override", + "@provides", + "@requires", + "@shareable", + "@tag" + ] + ) + @link(url: "https://myspecs.dev/myCustomDirective/v1.0", import: ["@custom"]) + @composeDirective(name: "@custom") + +directive @custom on OBJECT + +type Product @custom @key(fields: "id") @key(fields: "sku package") @key(fields: "sku variation { id }") { + id: ID! + sku: String + package: String + variation: ProductVariation + dimensions: ProductDimension + createdBy: User @provides(fields: "totalProductsCreated") + notes: String @tag(name: "internal") + research: [ProductResearch!]! } type DeprecatedProduct @key(fields: "sku package") { - sku: String! - package: String! - reason: String - createdBy: User + sku: String! + package: String! + reason: String + createdBy: User } type ProductVariation { - id: ID! + id: ID! } type ProductResearch @key(fields: "study { caseNumber }") { - study: CaseStudy! - outcome: String + study: CaseStudy! + outcome: String } type CaseStudy { - caseNumber: ID! - description: String + caseNumber: ID! + description: String } type ProductDimension @shareable { - size: String - weight: Float - unit: String @inaccessible + size: String + weight: Float + unit: String @inaccessible } extend type Query { - product(id: ID!): Product - deprecatedProduct(sku: String!, package: String!): DeprecatedProduct @deprecated(reason: "Use product query instead") + product(id: ID!): Product + deprecatedProduct(sku: String!, package: String!): DeprecatedProduct @deprecated(reason: "Use product query instead") } type User @extends @key(fields: "email") { - averageProductsCreatedPerYear: Int @requires(fields: "totalProductsCreated yearsOfEmployment") - email: ID! @external - name: String @override(from: "users") - totalProductsCreated: Int @external - yearsOfEmployment: Int! @external + averageProductsCreatedPerYear: Int @requires(fields: "totalProductsCreated yearsOfEmployment") + email: ID! @external + name: String @override(from: "users") + totalProductsCreated: Int @external + yearsOfEmployment: Int! @external +} + +type Inventory @interfaceObject @key(fields: "id") { + id: ID! + deprecatedProducts: [DeprecatedProduct!]! }