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) 獲得許可。