HotChocolate.Extensions.ApolloSubgraph
0.3.0
dotnet add package HotChocolate.Extensions.ApolloSubgraph --version 0.3.0
NuGet\Install-Package HotChocolate.Extensions.ApolloSubgraph -Version 0.3.0
<PackageReference Include="HotChocolate.Extensions.ApolloSubgraph" Version="0.3.0" />
paket add HotChocolate.Extensions.ApolloSubgraph --version 0.3.0
#r "nuget: HotChocolate.Extensions.ApolloSubgraph, 0.3.0"
// Install HotChocolate.Extensions.ApolloSubgraph as a Cake Addin #addin nuget:?package=HotChocolate.Extensions.ApolloSubgraph&version=0.3.0 // Install HotChocolate.Extensions.ApolloSubgraph as a Cake Tool #tool nuget:?package=HotChocolate.Extensions.ApolloSubgraph&version=0.3.0
HotChocolate.Extensions.ApolloSubgraph ☕ 🚀
This package extends the HotChocolate GraphQL server with support for building Apollo Federation subgraphs.
Getting Started
Add the Apollo Federation support to the schema by using the AddApolloSubgraph
extension method when configuring services
during start-up, e.g.
services.AddGraphQLServer()
.AddApolloSubgraph();
The package supports all three paradigms for writing subgraphs in HotChocolate.
The following examples are based on the Apollo reviews subgraph schema.
Example User Type (SDL)
type User @extends @key(fields: "id") {
id: ID! @external
username: String @external
reviews: [Review]
}
Code-first
The code-first approach uses extension methods to specify directives using descriptors and a func-based entity resolver.
The object-type can specify the
@extends
and@key
directives using theExtends
andKey
extension methods.The field-type can specify the
@key
,@provides
and@requires
directives using theKey
,Provides
andRequires
extension methods.The reference resolver for the entity can be specified using the
ResolveEntity
extension method.
Example User Type (Code-first)
public class UserType : ObjectType<User>
{
protected override void Configure(IObjectTypeDescriptor<User> descriptor)
{
descriptor.Extends();
descriptor.Key(x => x.Id);
descriptor.Field(x => x.Id).Type<NonNullType<IdType>>();
descriptor.Field(x => x.Username).Type<StringType>().External();
descriptor.Field(x => x.GetReviews(default)).Type<ListType<ReviewType>>();
descriptor.ResolveEntity(x => new User(x.Representation.GetValue<string>("id")));
}
}
See CodeFirstTest.cs for a complete example.
Type Extensions
The federation directives and entity resolver can also be specified using a type extension if you cannot modify the original types.
public class UserTypeExtension : ObjectTypeExtension<User>
{
protected override void Configure(IObjectTypeDescriptor<User> descriptor)
{
descriptor.Extends();
descriptor.Key(x => x.Id);
descriptor.Field(x => x.Username).External();
descriptor.ResolveEntity(x => new User(x.Representation.GetValue<string>("id")));
}
}
Annotations-based
The annotations-based approach uses attributes to decorate types and a convention-based entity resolver method.
The type can specify the
@extends
and@key
directives using theGraphQLExtends
andGraphQLKey
attributes.The type properties can specify the
@key
,@provides
and@requires
directives using theGraphQLKey
,GraphQLProvides
andGraphQLRequires
attributes.The reference resolver for the entity is be specified by adding a
ResolveEntity
(returnsT
) orResolveEntityAsync
(returnsTask<T>
) method to the type.If you want to use a different method name or prefer to be explicit, the
EntityResolver
attribute can be used to annotate method with a matching signature.
Example User Type (Annotations-based)
[GraphQLExtends]
public sealed record User
{
public User(string id, string username)
{
Id = id;
Username = username;
}
[GraphQLKey]
[GraphQLExternal]
[GraphQLType(typeof(IdType))]
public string Id { get; }
[GraphQLExternal]
public string Username { get; }
public IReadOnlyList<Review> GetReviews()
{
return Array.Empty<Review>();
}
public static User? ResolveEntity(IEntityResolverContext context)
{
return new User(context.Representation.GetValue<string>("id"));
}
}
See AnnotationsTest.cs for a complete example.
Type Extensions
The federation directives and entity resolver can also be specified using a type extension if you cannot modify the original types.
[ExtendObjectType(typeof(User))]
[GraphQLExtends]
[GraphQLKey("upc")]
[GraphQLExternal("username")]
public class UserExtensions
{
public static User ResolveEntity(IEntityResolverContext context)
{
return new User(context.Representation.GetValue<string>("id"));
}
}
Schema-first
The schema-first approach uses attributes to decorate bound types and a func-based entity resolver.
The
@extends
,@key
,@provides
and@requires
directives are specified in the schema for object-types and fields.The reference resolver for the entity can be specified using the
AddEntityResolver
extension method or by using the convention-based resolver method (see Annotations-based).
⚠️ Use the @extends
directive for types that are defined in another subgraph (extend type
is not supported)!
Example User Type (Schema-first)
services.AddGraphQLServer()
.AddApolloSubgraph()
.AddDocumentFromString(@"
type User @extends @key(fields: ""id"") {
id: ID! @external
username: String @external
reviews: [Review]
}
type Review
type Query
")
.BindRuntimeType<User>()
.AddEntityResolver(x => new User(x.Representation.GetValue<string>("id")));
public record User(string Id, string Username = null)
{
public IReadOnlyList<Review> GetReviews()
{
return Array.Empty<Review>();
}
}
The convention-based entity resolver will be used if a ResolveEntity
or ResolveEntityAsync
method is added to the
bound type.
public record User(string Id, string Username = null)
{
public IReadOnlyList<Review> GetReviews()
{
return Array.Empty<Review>();
}
public static User? ResolveEntity(IEntityResolverContext context)
{
return new User(context.Representation.GetValue<string>("id"));
}
}
See SchemaFirstTest.cs for a complete example.
Entity Resolvers
The entity resolver (also known as a reference resolver) enables the gateway to resolve an
entity by its @key
fields.
Entity resolvers are represented by the EntityResolverDelegate
and are invoked with a context that provides access
to the representation specified in the query to the _entities
field.
The delegate is asynchronous but overloads are also provided for resolvers which are synchronous.
The convention-based method supports either ResolveEntity
(returns T
) and ResolveEntityAsync
(returns Task<T>
)
signatures, or any method name if a matching method is annotated with the EntityResolver
attribute.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- HotChocolate (>= 12.4.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
0.3.0 | 16,085 | 1/23/2022 |
0.2.0-preview50 | 391 | 1/16/2022 |
0.1.0-preview46 | 381 | 1/10/2022 |
0.1.0-preview43 | 358 | 1/9/2022 |