Skip to content

Commit

Permalink
Revamp federation resolvers (#3960)
Browse files Browse the repository at this point in the history
  • Loading branch information
Shane32 committed Jun 9, 2024
1 parent 8d2b0bc commit 4023803
Show file tree
Hide file tree
Showing 25 changed files with 1,157 additions and 145 deletions.
54 changes: 49 additions & 5 deletions docs2/site/docs/migrations/migration8.md
Original file line number Diff line number Diff line change
Expand Up @@ -623,17 +623,61 @@ Unless you directly implement these interfaces, you should not be impacted by th
See the new features section for details on the new method added to this interface.
Unless you directly implement this interface, you should not be impacted by this change.

### 15. `AnyScalarType` moved to `GraphQL.Federation.Types`
### 15. `AnyScalarType` and `ServiceGraphType` moved to `GraphQL.Federation.Types`

`GraphQL.Utilities.Federation.AnyScalarType` has been moved to `GraphQL.Federation.Types.AnyScalarType`.
All federation types are now located within the `GraphQL.Federation.Types` namespace.
These graph types, previously located within the `GraphQL.Utilities.Federation` namespace,
have been moved to the `GraphQL.Federation.Types` namespace alongside all other federation types.

### 16. `IInputObjectGraphType.IsOneOf` property added
### 16. `IFederatedResolver`, `FuncFederatedResolver` and `ResolveReferenceAsync` replaced

- `IFederatedResolver` has been replaced with `IFederationResolver`.
- `FuncFederatedResolver` has been replaced with `FederationResolver`.
- `ResolveReferenceAsync` has been replaced with `ResolveReference`.

Please note that the new members are now located in the `GraphQL.Federation` namespace and may
require slight changes to your code to accommodate the new signatures. The old members have been
marked as obsolete and will continue to work in v8, but will be removed in v9.

### 17. GraphQL Federation entity resolvers do not automatically inject `__typename` into requests.

Previously, the `__typename` field was automatically injected into the request for entity resolvers.
This behavior has been removed as it is not required to meet the GraphQL Federation specification.

For instance, the following sample request:

```graphql
{
_entities(representations: [{ __typename: "User", id: "1" }]) {
... on User {
id
}
}
}
```

Should now be written as:

```graphql
{
_entities(representations: [{ __typename: "User", id: "1" }]) {
__typename
... on User {
id
}
}
}
```

Please ensure that your client requests are updated to include the `__typename` field in the response.
Alternatively, you can install the provided `InjectTypenameValidationRule` validation rule to automatically
inject the `__typename` field into the request.

### 18. `IInputObjectGraphType.IsOneOf` property added

See the new features section for details on the new property added to this interface.
Unless you directly implement this interface, you should not be impacted by this change.

### 17. `VariableUsage.IsRequired` property added and `VariableUsage` constructor changed
### 19. `VariableUsage.IsRequired` property added and `VariableUsage` constructor changed

This is required for OneOf Input Object support and is used to determine if a variable is required.
Unless you have a custom validation rule that uses `VariableUsage`, you should not be impacted
Expand Down
77 changes: 71 additions & 6 deletions src/GraphQL.ApiTests/net50/GraphQL.approved.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1525,6 +1525,13 @@ namespace GraphQL.Federation
public static TMetadataWriter Shareable<TMetadataWriter>(this TMetadataWriter graphType)
where TMetadataWriter : GraphQL.Types.IFieldMetadataWriter { }
}
public static class FederationGraphTypeExtensions
{
public static void ResolveReference<TSourceType>(this GraphQL.Types.ObjectGraphType<TSourceType> graphType, GraphQL.Federation.Resolvers.IFederationResolver resolver) { }
public static void ResolveReference<TSourceType, TReturnType>(this GraphQL.Types.ObjectGraphType<TSourceType> graphType, System.Func<GraphQL.IResolveFieldContext, TSourceType, GraphQL.DataLoader.IDataLoaderResult<TReturnType?>> resolver) { }
public static void ResolveReference<TSourceType, TReturnType>(this GraphQL.Types.ObjectGraphType<TSourceType> graphType, System.Func<GraphQL.IResolveFieldContext, TSourceType, System.Threading.Tasks.Task<TReturnType?>> resolver) { }
public static void ResolveReference<TSourceType, TReturnType>(this GraphQL.Types.ObjectGraphType<TSourceType> graphType, System.Func<GraphQL.IResolveFieldContext, TSourceType, TReturnType?> resolver) { }
}
public static class FederationInterfaceMetadataExtensions
{
public static TMetadataWriter Key<TMetadataWriter>(this TMetadataWriter graphType, string[] fields, bool resolvable = true)
Expand Down Expand Up @@ -1555,6 +1562,16 @@ namespace GraphQL.Federation
public override void Modify(GraphQL.Types.IGraphType graphType) { }
public override void Modify(GraphQL.Types.FieldType fieldType, bool isInputType) { }
}
[System.Obsolete("This class will be removed in GraphQL.NET v9.")]
public class InjectTypenameValidationRule : GraphQL.Validation.INodeVisitor, GraphQL.Validation.IValidationRule
{
public InjectTypenameValidationRule() { }
public System.Threading.Tasks.ValueTask EnterAsync(GraphQLParser.AST.ASTNode node, GraphQL.Validation.ValidationContext context) { }
public System.Threading.Tasks.ValueTask<GraphQL.Validation.INodeVisitor?> GetPostNodeVisitorAsync(GraphQL.Validation.ValidationContext context) { }
public System.Threading.Tasks.ValueTask<GraphQL.Validation.INodeVisitor?> GetPreNodeVisitorAsync(GraphQL.Validation.ValidationContext context) { }
public System.Threading.Tasks.ValueTask<GraphQL.Validation.IVariableVisitor?> GetVariableVisitorAsync(GraphQL.Validation.ValidationContext context) { }
public System.Threading.Tasks.ValueTask LeaveAsync(GraphQLParser.AST.ASTNode node, GraphQL.Validation.ValidationContext context) { }
}
[System.AttributeUsage(System.AttributeTargets.Class, AllowMultiple=true)]
public class KeyAttribute : GraphQL.GraphQLAttribute
{
Expand Down Expand Up @@ -1591,6 +1608,51 @@ namespace GraphQL.Federation
public override void Modify(GraphQL.Types.IGraphType graphType) { }
public override void Modify(GraphQL.Types.FieldType fieldType, bool isInputType) { }
}
public static class TypeConfigExtensions
{
public static void ResolveReference(this GraphQL.Utilities.TypeConfig config, GraphQL.Federation.Resolvers.IFederationResolver resolver) { }
public static void ResolveReference<TSourceType>(this GraphQL.Utilities.TypeConfig typeConfig, System.Func<GraphQL.IResolveFieldContext, TSourceType, GraphQL.DataLoader.IDataLoaderResult<TSourceType?>> resolver) { }
public static void ResolveReference<TSourceType>(this GraphQL.Utilities.TypeConfig typeConfig, System.Func<GraphQL.IResolveFieldContext, TSourceType, System.Threading.Tasks.Task<TSourceType?>> resolver) { }
public static void ResolveReference<TSourceType>(this GraphQL.Utilities.TypeConfig typeConfig, System.Func<GraphQL.IResolveFieldContext, TSourceType, TSourceType?> resolver) { }
public static void ResolveReference<TSourceType, TReturnType>(this GraphQL.Utilities.TypeConfig config, System.Func<GraphQL.IResolveFieldContext, TSourceType, GraphQL.DataLoader.IDataLoaderResult<TReturnType?>> resolver) { }
public static void ResolveReference<TSourceType, TReturnType>(this GraphQL.Utilities.TypeConfig config, System.Func<GraphQL.IResolveFieldContext, TSourceType, System.Threading.Tasks.Task<TReturnType?>> resolver) { }
public static void ResolveReference<TSourceType, TReturnType>(this GraphQL.Utilities.TypeConfig config, System.Func<GraphQL.IResolveFieldContext, TSourceType, TReturnType?> resolver) { }
}
}
namespace GraphQL.Federation.Resolvers
{
public sealed class EntityResolver : GraphQL.Resolvers.IFieldResolver
{
public static GraphQL.Federation.Resolvers.EntityResolver Instance { get; }
public System.Collections.Generic.IEnumerable<GraphQL.Federation.Resolvers.Representation> ConvertRepresentations(GraphQL.Types.ISchema schema, System.Collections.IList representations) { }
public System.Threading.Tasks.ValueTask<object?> ResolveAsync(GraphQL.IResolveFieldContext context) { }
}
public class FederationResolver<TClrType> : GraphQL.Federation.Resolvers.FederationResolver<TClrType, TClrType>
{
public FederationResolver(System.Func<GraphQL.IResolveFieldContext, TClrType, GraphQL.DataLoader.IDataLoaderResult<TClrType?>> resolveFunc) { }
public FederationResolver(System.Func<GraphQL.IResolveFieldContext, TClrType, System.Threading.Tasks.Task<TClrType?>> resolveFunc) { }
public FederationResolver(System.Func<GraphQL.IResolveFieldContext, TClrType, TClrType?> resolveFunc) { }
}
public class FederationResolver<TSourceType, TReturnType> : GraphQL.Federation.Resolvers.IFederationResolver
{
public FederationResolver(System.Func<GraphQL.IResolveFieldContext, TSourceType, GraphQL.DataLoader.IDataLoaderResult<TReturnType?>> resolveFunc) { }
public FederationResolver(System.Func<GraphQL.IResolveFieldContext, TSourceType, System.Threading.Tasks.Task<TReturnType?>> resolveFunc) { }
public FederationResolver(System.Func<GraphQL.IResolveFieldContext, TSourceType, TReturnType?> resolveFunc) { }
public System.Type SourceType { get; }
public System.Threading.Tasks.ValueTask<object?> ResolveAsync(GraphQL.IResolveFieldContext context, object source) { }
}
public interface IFederationResolver
{
System.Type SourceType { get; }
System.Threading.Tasks.ValueTask<object?> ResolveAsync(GraphQL.IResolveFieldContext context, object source);
}
public class Representation : System.IEquatable<GraphQL.Federation.Resolvers.Representation>
{
public Representation(GraphQL.Types.IObjectGraphType GraphType, GraphQL.Federation.Resolvers.IFederationResolver Resolver, object Value) { }
public GraphQL.Types.IObjectGraphType GraphType { get; init; }
public GraphQL.Federation.Resolvers.IFederationResolver Resolver { get; init; }
public object Value { get; init; }
}
}
namespace GraphQL.Federation.Types
{
Expand Down Expand Up @@ -3285,22 +3347,25 @@ namespace GraphQL.Utilities.Federation
public override string PrintInterface(GraphQL.Types.IInterfaceGraphType type) { }
public override string PrintObject(GraphQL.Types.IObjectGraphType type) { }
}
public class FuncFederatedResolver<T> : GraphQL.Utilities.Federation.IFederatedResolver
[System.Obsolete("Please use the GraphQL.Federation.FederationResolver class instead. This class wi" +
"ll be removed in v9.")]
public class FuncFederatedResolver<TReturn> : GraphQL.Federation.Resolvers.FederationResolver<System.Collections.Generic.Dictionary<string, object?>, TReturn>, GraphQL.Utilities.Federation.IFederatedResolver
{
public FuncFederatedResolver(System.Func<GraphQL.Utilities.Federation.FederatedResolveContext, System.Threading.Tasks.Task<T?>> func) { }
public FuncFederatedResolver(System.Func<GraphQL.Utilities.Federation.FederatedResolveContext, System.Threading.Tasks.Task<TReturn?>> func) { }
public System.Threading.Tasks.Task<object?> Resolve(GraphQL.Utilities.Federation.FederatedResolveContext context) { }
}
[System.Obsolete("Please use IFederationResolver instead. This interface will be removed in v9.")]
public interface IFederatedResolver
{
System.Threading.Tasks.Task<object?> Resolve(GraphQL.Utilities.Federation.FederatedResolveContext context);
}
public class ServiceGraphType : GraphQL.Types.ObjectGraphType
{
public ServiceGraphType() { }
}
public static class TypeConfigExtensions
{
[System.Obsolete("Please use ResolveReference instead, found in the GraphQL.Federation namespace. T" +
"his method will be removed in v9.")]
public static void ResolveReferenceAsync(this GraphQL.Utilities.TypeConfig config, GraphQL.Utilities.Federation.IFederatedResolver resolver) { }
[System.Obsolete("Please use another overload instead, found in the GraphQL.Federation namespace. T" +
"his method will be removed in v9.")]
public static void ResolveReferenceAsync<T>(this GraphQL.Utilities.TypeConfig config, System.Func<GraphQL.Utilities.Federation.FederatedResolveContext, System.Threading.Tasks.Task<T?>> resolver) { }
}
}
Expand Down
Loading

0 comments on commit 4023803

Please sign in to comment.