HotChocolate.ApolloFederation
软件包现在完全支持 Federation v2。为了简化 HC 生态系统中的集成,我们决定弃用此软件包,转而支持单个功能齐全的内置软件包。警告由于公共 API 发生重大更改,在替换 API(当前正在进行中)完成之前,我们无法支持较新版本的
HotChocolate
。我们只能支持 v13.5.x
和 v13.6.x
版本。
Apollo Federation是一个强大的开放架构,可帮助您创建结合多个 GraphQL API 的统一超级图。 ApolloGraphQL.HotChocolate.Federation
为在HotChocolate
生态系统中构建子图提供 Apollo Federation 支持。各个子图可以彼此独立运行,但也可以使用联合指令指定与其他子图的关系。有关详细信息,请参阅 Apollo Federation 文档。
ApolloGraphQL.HotChocolate.Federation
包已发布到 Nuget。使用以下包引用更新您的.csproj
文件
< ItemGroup > < PackageReference Include = " HotChocolate.AspNetCore " Version = " 13.6.0 " /> < PackageReference Include = " ApolloGraphQL.HotChocolate.Federation " Version = " $LatestVersion " /> ItemGroup >
安装必要的软件包后,您需要向 GraphQL 服务注册 Apollo Federation。
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services
. AddGraphQLServer ( )
. AddApolloFederationV2 ( )
// register your types and services
;
var app = builder . Build ( ) ;
app . MapGraphQL ( ) ;
app . Run ( ) ;
如果您想选择加入 Federation v1 架构,则需要使用
.AddApolloFederation()
扩展。
有关如何创建 GraphQL 模式和配置服务器的详细信息,请参阅HotChocolate
文档。
Apollo Federation 要求子图提供一些额外的元数据,以使它们能够感知超级图。实体是 GraphQL 对象,可以通过指定的@key
在整个超图中唯一标识。由于实体可以通过各种子图进行扩展,因此我们需要一个额外的入口点来访问实体,即子图需要为它们支持的实体实现引用解析器。
有关联合的其他详细信息,请参阅 Apollo 文档。
所有联合指令都作为属性提供,可以直接应用于类/字段/方法。
[ Key ( " id " ) ]
public class Product
{
public Product ( string id , string name , string ? description )
{
Id = id ;
Name = name ;
Description = description ;
}
[ ID ]
public string Id { get ; }
public string Name { get ; }
public string ? Description { get ; }
// assumes ProductRepository with GetById method exists
// reference resolver method must be public static
[ ReferenceResolver ]
public static Product GetByIdAsync (
string id ,
ProductRepository productRepository )
=> productRepository . GetById ( id ) ;
}
这将生成以下类型
type Product @key ( fields : " id " ) {
id : ID !
name : String !
description : String
}
联邦 v1 指令
Extends
适用于对象,请参阅@extends
文档External
适用于字段,请参阅@external
文档Key
,请参阅@key
文档Provides
适用于字段,请参阅@provides
文档Requires
适用于字段,请参阅@requires
文档Federation v2 指令(包括所有 v1 指令)
ApolloTag
适用于模式,请参阅@tag
文档ApolloAuthenticated
(自 v2.5 起)适用于枚举、字段、接口和对象, @authenticated
文档ComposeDirective
(自 v2.1 起)适用于模式,请参阅@composeDirective
文档Contact
,请参阅@contact
用法Inaccessible
适用于所有类型定义,请参阅@inaccessible
文档InterfaceObject
(自 v2.3 起)适用于对象,请参阅@interfaceObject
文档KeyInterface
适用于接口,参见实体接口@key
文档Link
,请参阅@link
文档RequiresScopes
(自 v2.5 起)适用于枚举、字段、接口和对象, @requiresScopes
文档Shareable
适用于架构,请参阅@shareable
文档实体解析
Map
适用于实体解析器方法参数,允许您将复杂的参数映射到更简单的表示值,例如[Map("foo.bar")] string bar
ReferenceResolver
适用于实体类中的公共静态方法,以指示实体解析器或者,如果您需要更精细的控制,您可以使用代码优先方法并手动填充底层 GraphQL 类型描述符上的联合信息。所有联合指令都在适用的描述符上公开相应的方法。
public class Product
{
public Product ( string id , string name , string ? description )
{
Id = id ;
Name = name ;
Description = description ;
}
[ ID ]
public string Id { get ; }
public string Name { get ; }
public string ? Description { get ; }
}
public class ProductType : ObjectType < Product >
{
protected override void Configure ( IObjectTypeDescriptor < Product > descriptor )
{
descriptor
. Key ( " id " )
. ResolveReferenceWith ( t => GetProduct ( default ! , default ! ) ) ;
}
private static Product GetProduct (
string id ,
ProductRepository productRepository )
=> productRepository . GetById ( upc ) ;
}
这将生成以下类型
type Product @key ( fields : " id " ) {
id : ID !
name : String !
description : String
}
联邦 v1 指令
ExtendsType
适用于对象,请参阅@extends
文档External
适用于字段,请参阅@external
文档Key(fieldset)
适用于对象,请参阅@key
文档Provides(fieldset)
适用于字段,请参阅@provides
文档Requires(fieldset)
适用于字段,请参阅@requires
文档Federation v2 指令(包括所有 v1 指令)
ApolloTag
适用于所有类型定义,请参阅@tag
文档ApolloAuthenticated
(自 v2.5 起)适用于枚举、字段、接口和对象, @authenticated
文档ComposeDirective(name)
(自 v2.1 起)适用于模式,请参阅@composeDirective
文档Contact(name, url?, description?)
适用于模式,请参阅@contact
用法Inaccessible
适用于所有类型定义,请参阅@inaccessible
文档InterfaceObject
(自 v2.3 起)适用于对象,请参阅@interfaceObject
文档Key(fieldset)
适用于对象,请参阅@key
文档Link(url, [import]?)
适用于架构,请参阅@link
文档NonResolvableKey(fieldset)
适用于对象,请参阅不可解析的@key
文档RequiresScopes(scopes)
(自 v2.5 起)适用于枚举、字段、接口和对象, @requiresScopes
文档Shareable
适用于字段和对象,请参阅@shareable
文档实体解析
ResolveReferenceWith
函数才能解析实体有关命令行界面的服务器支持的详细信息,请参阅 HotChocolate 文档。为了在构建时生成架构,您需要添加对HotChocolate.AspNetCore.CommandLine
包的额外依赖项,并配置您的服务器以允许其RunWithGraphQLCommands
。
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services
. AddGraphQLServer ( )
. AddApolloFederationV2 ( )
// register your types and services
;
var app = builder . Build ( ) ;
app . MapGraphQL ( ) ;
app . RunWithGraphQLCommands ( args ) ;
然后您可以通过运行来生成您的架构
dotnet run -- schema export --output schema.graphql
默认情况下, ApolloGraphQL.HotChocolate.Federation
将使用最新支持的联合版本生成模式。如果您想选择使用旧版本,可以通过在配置AddApolloFederationV2
扩展时指定版本来实现。
builder . Services
. AddGraphQLServer ( )
. AddApolloFederationV2 ( FederationVersion . FEDERATION_23 )
// register your types and services
;
或者,您还可以提供针对特定联合版本的自定义FederatedSchema
public class CustomSchema : FederatedSchema
{
public CustomSchema ( ) : base ( FederationVersion . FEDERATION_23 ) {
}
}
builder . Services
. AddGraphQLServer ( )
. AddApolloFederationV2 ( new CustomSchema ( ) )
// register your types and services
;
如果您想通过应用一些指令来自定义架构,您还可以提供自定义FederatedSchema
,可以使用扩展SchemaTypeDescriptorAttribute
属性进行注释
[ AttributeUsage ( AttributeTargets . Class | AttributeTargets . Struct , Inherited = true , AllowMultiple = true ) ]
public sealed class CustomAttribute : SchemaTypeDescriptorAttribute
{
public override void OnConfigure ( IDescriptorContext context , ISchemaTypeDescriptor descriptor , Type type )
{
// configure your directive here
}
}
[ Custom ]
public class CustomSchema : FederatedSchema
{
public CustomSchema ( ) : base ( FederationVersion . FEDERATION_23 ) {
}
}
builder . Services
. AddGraphQLServer ( )
. AddApolloFederationV2 ( new CustomSchema ( ) )
// register your types and services
;
或者,您还可以在构建联合子图时指定自定义模式配置操作
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services
. AddGraphQLServer ( )
. AddApolloFederationV2 ( schemaConfiguration : s =>
{
// apply your directive here
} )
// register your types and services
;
@key
您的子图可以使用实体作为字段的返回类型,而无需向该实体提供任何字段。由于我们仍然需要类型定义来生成有效的模式,因此我们可以使用[NonResolvableKeyAttribute]
定义一个存根对象。
public class Review {
public Review ( Product product , int score )
{
Product = product ;
Score = score
}
public Product Product { get ; }
public int Score { get ; }
}
[ NonResolvableKey ( " id " ) ]
public class Product {
public Product ( string id )
{
Id = id ;
}
public string Id { get ; }
}
@composedDirective
用法默认情况下,Supergraph 模式排除所有自定义指令。 @composeDirective
用于指定应保留在 Supergraph 模式中的自定义指令。
ApolloGraphQL.HotChocolate.Federation
提供通用的FederatedSchema
类,自动应用 Apollo Federation v2 @link
定义。应用任何自定义架构指令时,您应该扩展此类并添加所需的属性/指令。
当应用@composedDirective
时,您还需要@link
它您的规范。然后,您的自定义架构应传递到AddApolloFederationV2
扩展。
[ ComposeDirective ( " @custom " ) ]
[ Link ( " https://myspecs.dev/myCustomDirective/v1.0 " , new string [ ] { " @custom " } ) ]
public class CustomSchema : FederatedSchema
{
}
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services
. AddGraphQLServer ( )
. AddApolloFederationV2 ( new CustomSchema ( ) )
// register your types and services
;
或者,您可以通过使用配置操作直接将@composedDirective
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services
. AddGraphQLServer ( )
. AddApolloFederationV2 ( schemaConfiguration : s =>
{
s . Link ( " https://myspecs.dev/myCustomDirective/v1.0 " , new string [ ] { " @custom " } ) ;
s . ComposeDirective ( " @custom " ) ;
} )
// register your types and services
;
@interfaceObject
用法Apollo Federation v2 支持实体接口,这是 GraphQL 接口的强大扩展,允许您跨超图扩展接口的功能,而无需实现(甚至不知道)其所有实现类型。
在定义接口的子图中,我们需要应用@key
[ InterfaceType ]
[ KeyInterface ( " id " ) ]
public interface Product
{
[ ID ]
string Id { get ; }
string Name { get ; }
}
[ Key ( " id " ) ]
public class Book : Product
{
[ ID ]
public string Id { get ; set ; }
public string Name { get ; set ; }
public string Content { get ; set ; }
}
然后,我们可以通过使其成为一种类型、应用@interfaceObject
和相同的@key
指令来扩展另一个子图中的接口。这允许您向实现接口的每个实体添加新字段(例如,向所有Product
实现添加Reviews
字段)。
[ Key ( " id " ) ]
[ InterfaceObject ]
public class Product
{
[ ID ]
public string Id { get ; set ; }
public List < string > Reviews { get ; set ; }
}
@requiresScopes
指令用于指示目标元素只能由具有适当 JWT 范围的经过身份验证的超级图用户访问。有关更多详细信息,请参阅 Apollo 路由器文章。
public class Query
{
[ RequiresScopes ( scopes : new string [ ] { " scope1, scope2 " , " scope3 " } ) ]
[ RequiresScopes ( scopes : new string [ ] { " scope4 " } ) ]
public Product ? GetProduct ( [ ID ] string id , Data repository )
=> repository . Products . FirstOrDefault ( t => t . Id . Equals ( id ) ) ;
}
这将生成以下架构
type Query {
product ( id : ID ! ): Product @requiresScopes ( scopes : [ [ " scope1, scope2 " , " scope3 " ], [ " scope4 " ] ])
}
您可以使用@contact
指令将团队的联系信息添加到子图架构中。此信息显示在 Studio 中,这有助于其他团队了解应联系谁来获取有关子图的帮助。有关详细信息,请参阅文档。
我们需要在模式上应用[Contact]
属性。您可以在自定义架构上应用[Contact]
属性,并将自定义架构传递给AddApolloFederationV2
扩展。
[ Contact ( " MyTeamName " , " https://myteam.slack.com/archives/teams-chat-room-url " , " send urgent issues to [#oncall](https://yourteam.slack.com/archives/oncall) " ) ]
public class CustomSchema : FederatedSchema
{
}
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services
. AddGraphQLServer ( )
. AddType < ContactDirectiveType > ( ) ;
. AddApolloFederationV2 ( new CustomSchema ( ) )
// register your types and services
;
或通过提供自定义架构配置操作直接在架构上应用@contact
指令
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services
. AddGraphQLServer ( )
. AddApolloFederationV2 ( schemaConfiguration : s =>
{
s . Contact ( " MyTeamName " , " https://myteam.slack.com/archives/teams-chat-room-url " , " send urgent issues to [#oncall](https://yourteam.slack.com/archives/oncall) " ) ;
} )
// register your types and services
;
ApolloGraphQL.HotChocolate.Federation
自动默认使用Query
类型名称。使用自定义根Query
操作类型时,您必须使用这些自定义值显式配置架构。
public class CustomQuery
{
public Foo ? GetFoo ( [ ID ] string id , Data repository )
=> repository . Foos . FirstOrDefault ( t => t . Id . Equals ( id ) ) ;
}
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services
. AddGraphQLServer ( )
. ModifyOptions ( opts => opts . QueryTypeName = " CustomQuery " )
. AddApolloFederationV2 ( )
. AddQueryType < CustomQuery > ( )
// register your other types and services
;
var app = builder . Build ( ) ;
app . MapGraphQL ( ) ;
app . Run ( ) ;
从HotChocolate.Federation
迁移到ApolloGraphQL.HotChocolate.Federation
很容易。只需更新您的包导入以指向新模块
- +
并更新命名空间导入
- using HotChocolate.ApolloFederation;
+ using ApolloGraphQL.HotChocolate.Federation;
虽然我们试图使迁移过程尽可能无缝,但我们必须对库进行一些调整。由于依赖某些内部 API,我们必须对库进行以下重大更改:
[Key]
现在仅适用于课程,您不能再将其应用于单个字段[ReferenceResolver]
现在仅适用于实体内的公共静态方法,不再适用于类[EntityResolver]
可以自动将实体表示映射到支持的@key
/ @requires
值。标量@key
字段会自动映射,我们可以使用[Map]
属性自动映射复杂选择集中的标量值。
目前我们不支持列表和对象值的自动映射。
作为解决方法,您需要在实现中手动解析表示对象。
[ ReferenceResolver ]
public static Foo GetByFooBar (
[ LocalState ] ObjectValueNode data
Data repository )
{
// TODO implement logic here by manually reading values from local state data
}
@link
支持目前我们仅支持从引用的子图中导入元素。
目前不支持命名空间和重命名元素。详情请参阅问题。
如果您对库或代码有具体问题,请在 Apollo 社区论坛中开始讨论或在我们的 Discord 服务器上开始对话。
首先,请分叉存储库并签出一个新分支。然后,您可以通过运行在本地构建库
# install dependencies
dotnet restore
# build project
dotnet build
# run tests
dotnet test
请参阅 CONTRIBUTING.md 中的更多信息。
在您建立本地分支机构后,请查看我们的未解决问题,看看您可以在哪些方面做出贡献。
有关如何联系团队解决安全问题的更多信息,请参阅我们的安全政策。
该库根据 MIT 许可证 (MIT) 获得许可。