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 > < PackageReference Include = " HotChocolate.AspNetCore " Version = " 13.6.0 " /> < 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
への移行は簡単です。新しいモジュールを指すようにパッケージのインポートを更新するだけです
- +
名前空間のインポートを更新します
- 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) に基づいてライセンスされています。