HotChocolate.ApolloFederationパッケージは Federation v2 を完全にサポートするようになりました。 HC エコシステムでの統合を簡素化するために、完全な機能を備えた単一の組み込みパッケージをサポートすることを優先し、このパッケージを非推奨にすることを決定しました。警告パブリック API に対する重大な変更のため、代替 API (現在作業中) が完了するまで、新しいバージョンの
HotChocolateをサポートできません。当社がサポートできるのは、v13.5.xおよび v13.6.xリリースのみです。
Apollo Federation は、複数の GraphQL API を組み合わせた統合スーパーグラフの作成に役立つ強力なオープン アーキテクチャです。 ApolloGraphQL.HotChocolate.Federation HotChocolateエコシステムでサブグラフを構築するための Apollo Federation サポートを提供します。個々のサブグラフは互いに独立して実行できますが、Federated ディレクティブを使用して他のサブグラフとの関係を指定することもできます。詳細については、Apollo Federation のドキュメントを参照してください。
ApolloGraphQL.HotChocolate.Federationパッケージが Nuget に公開されます。次のパッケージ参照を使用して.csprojファイルを更新します。
< ItemGroup >
<!-- make sure to also include HotChocolate package -->
< PackageReference Include = " HotChocolate.AspNetCore " Version = " 13.6.0 " />
<!-- federation package -->
< PackageReference Include = " ApolloGraphQL.HotChocolate.Federation " Version = " $LatestVersion " />
</ ItemGroup >必要なパッケージをインストールした後、Apollo Federation を GraphQL サービスに登録する必要があります。
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 では、サブグラフがスーパーグラフを認識できるようにするために、追加のメタデータを提供する必要があります。エンティティは、指定された@keyによってスーパーグラフ全体で一意に識別できる GraphQL オブジェクトです。エンティティはさまざまなサブグラフによって拡張できるため、エンティティにアクセスするための追加のエントリ ポイントが必要です。つまり、サブグラフはサポートするエンティティの参照リゾルバを実装する必要があります。
フェデレーションの詳細については、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ドキュメントを参照してください。フェデレーション 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ドキュメントを参照してください。フェデレーション 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
;いくつかのディレクティブを適用してスキーマをカスタマイズしたい場合は、 SchemaTypeDescriptorAttribute拡張する属性で注釈を付けることができるカスタムFederatedSchemaを提供することもできます。
[ 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 Apollo Federation v2 @link定義を自動的に適用する共通のFederatedSchemaクラスを提供します。カスタム スキーマ ディレクティブを適用する場合は、このクラスを拡張し、必要な属性/ディレクティブを追加する必要があります。
@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 Router の記事を参照してください。
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への移行は簡単です。新しいモジュールを指すようにパッケージのインポートを更新するだけです
<ItemGroup>
<!-- make sure to also include HotChocolate package -->
<PackageReference Include="HotChocolate.AspNetCore" Version="13.6.0" />
<!-- federation package -->
- <PackageReference Include="HotChocolate.ApolloFederation" Version="$LatestVersion" />
+ <PackageReference Include="ApolloGraphQL.HotChocolate.Federation" Version="$LatestVersion" />
</ItemGroup>名前空間のインポートを更新します
- 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 を参照してください。
ローカルブランチを設定したら、未解決の問題を参照して、どこに貢献できるかを確認してください。
セキュリティの問題についてチームに連絡する方法の詳細については、セキュリティ ポリシーを参照してください。