HotChocolate.ApolloFederation
-Paket Federation v2 nun vollständig. Um die Integrationen im HC-Ökosystem zu vereinfachen, haben wir beschlossen, dieses Paket abzulehnen und stattdessen ein einzelnes integriertes Paket mit vollem Funktionsumfang zu unterstützen.Warnung Aufgrund einer bahnbrechenden Änderung an der öffentlichen API können wir neuere Versionen von
HotChocolate
erst dann unterstützen, wenn die Ersatz-API (derzeit in Arbeit) fertiggestellt ist. Wir können nur die Versionen v13.5.x
und v13.6.x
unterstützen .
Apollo Federation ist eine leistungsstarke, offene Architektur, die Ihnen hilft, einen einheitlichen Supergraphen zu erstellen, der mehrere GraphQL-APIs kombiniert. ApolloGraphQL.HotChocolate.Federation
bietet Apollo Federation-Unterstützung für die Erstellung von Untergraphen im HotChocolate
Ökosystem. Einzelne Untergraphen können unabhängig voneinander ausgeführt werden, können aber auch mithilfe von Federated-Direktiven Beziehungen zu den anderen Untergraphen angeben. Weitere Informationen finden Sie in der Dokumentation der Apollo Federation.
ApolloGraphQL.HotChocolate.Federation
-Paket wird auf Nuget veröffentlicht. Aktualisieren Sie Ihre .csproj
Datei mit den folgenden Paketverweisen
< ItemGroup > < PackageReference Include = " HotChocolate.AspNetCore " Version = " 13.6.0 " /> < PackageReference Include = " ApolloGraphQL.HotChocolate.Federation " Version = " $LatestVersion " /> ItemGroup >
Nach der Installation der erforderlichen Pakete müssen Sie Apollo Federation bei Ihrem GraphQL-Dienst registrieren.
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services
. AddGraphQLServer ( )
. AddApolloFederationV2 ( )
// register your types and services
;
var app = builder . Build ( ) ;
app . MapGraphQL ( ) ;
app . Run ( ) ;
Wenn Sie sich für das Federation v1-Schema entscheiden möchten, müssen Sie stattdessen die Erweiterung
.AddApolloFederation()
verwenden.
Ausführliche Informationen zum Erstellen von GraphQL-Schemas und zum Konfigurieren Ihres Servers finden Sie in HotChocolate
-Dokumentation.
Apollo Federation verlangt von Untergraphen, dass sie einige zusätzliche Metadaten bereitstellen, um sie für Supergraphen zu sensibilisieren. Entitäten sind GraphQL-Objekte, die durch die angegebenen @key
s im gesamten Supergraphen eindeutig identifiziert werden können. Da Entitäten durch verschiedene Untergraphen erweitert werden können, benötigen wir einen zusätzlichen Einstiegspunkt für den Zugriff auf die Entitäten, dh Untergraphen müssen Referenz-Resolver für Entitäten implementieren, die sie unterstützen.
Weitere Informationen zur Föderation finden Sie in der Apollo-Dokumentation.
Alle föderierten Direktiven werden als Attribute bereitgestellt, die direkt auf Klassen/Felder/Methoden angewendet werden können.
[ 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 ) ;
}
Dadurch wird der folgende Typ generiert
type Product @key ( fields : " id " ) {
id : ID !
name : String !
description : String
}
Federation v1-Anweisungen
Extends
anwendbar auf Objekte, siehe @extends
DokumentationExternal
anwendbar auf Felder, siehe @external
-DokumentationKey
, siehe @key
-DokumentationProvides
Anwendbarkeit auf Felder, siehe @provides
-DokumentationRequires
anwendbar auf Felder, siehe @requires
DokumentationFederation v2-Anweisungen (einschließlich aller v1-Anweisungen)
ApolloTag
anwendbar auf Schema, siehe @tag
-DokumentationApolloAuthenticated
(seit v2.5) anwendbar auf Enumeration, Feld, Schnittstelle und Objekt, @authenticated
-DokumentationComposeDirective
(seit v2.1) anwendbar auf Schema, siehe @composeDirective
-DokumentationContact
, siehe @contact
-NutzungInaccessible
anwendbar auf alle Typdefinitionen, siehe @inaccessible
-DokumentationInterfaceObject
(seit v2.3), anwendbar auf Objekte, siehe @interfaceObject
-DokumentationKeyInterface
gilt für Schnittstellen, siehe Dokumentation zur Entitätsschnittstelle @key
Link
anwendbar auf Schema, siehe @link
-DokumentationRequiresScopes
(seit v2.5) anwendbar auf Enum, Feld, Schnittstelle und Objekt, @requiresScopes
-DokumentationShareable
anwendbar auf Schema, siehe @shareable
-DokumentationEntitätsauflösung
Map
ermöglicht Ihnen die Zuordnung komplexer Argumente zu einem einfacheren Darstellungswert, z. B. [Map("foo.bar")] string bar
ReferenceResolver
anwendbar auf öffentliche statische Methoden innerhalb einer Entitätsklasse, um den Entitätsresolver anzugebenWenn Sie eine detailliertere Kontrolle benötigen, können Sie alternativ den Code-First-Ansatz verwenden und die Föderationsinformationen manuell in den zugrunde liegenden GraphQL-Typdeskriptor einfügen. Alle föderierten Direktiven stellen entsprechende Methoden für den entsprechenden Deskriptor bereit.
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 ) ;
}
Dadurch wird der folgende Typ generiert
type Product @key ( fields : " id " ) {
id : ID !
name : String !
description : String
}
Federation v1-Anweisungen
ExtendsType
gilt für Objekte, siehe @extends
DokumentationExternal
anwendbar auf Felder, siehe @external
-DokumentationKey(fieldset)
, siehe @key
-DokumentationProvides(fieldset)
, siehe @provides
-DokumentationRequires(fieldset)
gilt für Felder, siehe @requires
-DokumentationFederation v2-Anweisungen (einschließlich aller v1-Anweisungen)
ApolloTag
gilt für alle Typdefinitionen, siehe @tag
-DokumentationApolloAuthenticated
(seit v2.5) anwendbar auf Enumeration, Feld, Schnittstelle und Objekt, @authenticated
-DokumentationComposeDirective(name)
(seit v2.1) anwendbar auf Schema, siehe @composeDirective
-DokumentationContact(name, url?, description?)
anwendbar auf das Schema, siehe Verwendung @contact
Inaccessible
anwendbar auf alle Typdefinitionen, siehe @inaccessible
-DokumentationInterfaceObject
(seit v2.3), anwendbar auf Objekte, siehe @interfaceObject
-DokumentationKey(fieldset)
, siehe @key
-DokumentationLink(url, [import]?)
gilt für das Schema, siehe @link
-DokumentationNonResolvableKey(fieldset)
gilt für Objekte, siehe Dokumentation zu nicht auflösbaren @key
RequiresScopes(scopes)
(seit v2.5) anwendbar auf Enumeration, Feld, Schnittstelle und Objekt, @requiresScopes
-DokumentationShareable
gilt für Felder und Objekte, siehe @shareable
-DokumentationEntitätsauflösung
ResolveReferenceWith
bereitstellen, um die Entitäten auflösen zu können Einzelheiten zur Serverunterstützung für die Befehlszeilenschnittstelle finden Sie in der HotChocolate-Dokumentation. Um ein Schema zur Erstellungszeit zu generieren, müssen Sie eine zusätzliche Abhängigkeit vom Paket HotChocolate.AspNetCore.CommandLine
hinzufügen und Ihren Server so konfigurieren, dass er RunWithGraphQLCommands
zulässt.
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services
. AddGraphQLServer ( )
. AddApolloFederationV2 ( )
// register your types and services
;
var app = builder . Build ( ) ;
app . MapGraphQL ( ) ;
app . RunWithGraphQLCommands ( args ) ;
Anschließend können Sie Ihr Schema durch Ausführen generieren
dotnet run -- schema export --output schema.graphql
Standardmäßig generiert ApolloGraphQL.HotChocolate.Federation
ein Schema mit der neuesten unterstützten Federation-Version. Wenn Sie sich für die Verwendung älterer Versionen entscheiden möchten, können Sie dies tun, indem Sie bei der Konfiguration AddApolloFederationV2
Erweiterung die Version angeben.
builder . Services
. AddGraphQLServer ( )
. AddApolloFederationV2 ( FederationVersion . FEDERATION_23 )
// register your types and services
;
Alternativ können Sie auch ein benutzerdefiniertes FederatedSchema
bereitstellen, das auf eine bestimmte Federation-Version abzielt
public class CustomSchema : FederatedSchema
{
public CustomSchema ( ) : base ( FederationVersion . FEDERATION_23 ) {
}
}
builder . Services
. AddGraphQLServer ( )
. AddApolloFederationV2 ( new CustomSchema ( ) )
// register your types and services
;
Wenn Sie Ihr Schema durch die Anwendung einiger Anweisungen anpassen möchten, können Sie auch ein benutzerdefiniertes FederatedSchema
bereitstellen, das mit Attributen versehen werden kann, SchemaTypeDescriptorAttribute
erweitern
[ 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
;
Alternativ können Sie beim Erstellen eines föderierten Untergraphen auch eine benutzerdefinierte Schemakonfigurationsaktion angeben
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services
. AddGraphQLServer ( )
. AddApolloFederationV2 ( schemaConfiguration : s =>
{
// apply your directive here
} )
// register your types and services
;
@key
Ihre Untergraphen können eine Entität als Rückgabetyp eines Feldes verwenden, ohne Felder zu dieser Entität beizutragen. Da wir noch eine Typdefinition benötigen, um ein gültiges Schema zu generieren, können wir ein Stub- Objekt mit [NonResolvableKeyAttribute]
definieren.
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
Standardmäßig schließt das Supergraph-Schema alle benutzerdefinierten Anweisungen aus. Die @composeDirective
wird verwendet, um benutzerdefinierte Direktiven anzugeben, die im Supergraph-Schema beibehalten werden sollen.
ApolloGraphQL.HotChocolate.Federation
stellt eine gemeinsame FederatedSchema
Klasse bereit, die automatisch @link
-Definition von Apollo Federation v2 anwendet. Wenn Sie benutzerdefinierte Schemaanweisungen anwenden, sollten Sie diese Klasse erweitern und erforderliche Attribute/Anweisungen hinzufügen.
Wenn Sie @composedDirective
anwenden, müssen Sie es auch mit Ihrer Spezifikation @link
. Ihr benutzerdefiniertes Schema sollte dann an die AddApolloFederationV2
Erweiterung übergeben werden.
[ 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
;
Alternativ können Sie @composedDirective
anwenden, indem Sie es mithilfe der Konfigurationsaktion direkt auf ein Zielschema anwenden
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 unterstützt Entity-Schnittstellen , eine leistungsstarke Erweiterung der GraphQL-Schnittstellen, die es Ihnen ermöglicht, die Funktionalität einer Schnittstelle über den Supergraphen hinweg zu erweitern, ohne alle implementierenden Typen implementieren (oder sich überhaupt darüber im Klaren sein) zu müssen.
In einem Untergraphen, der die Schnittstelle definiert, müssen wir @key
anwenden
[ 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 ; }
}
Anschließend können wir die Schnittstelle in einem anderen Untergraphen erweitern, indem wir sie zu einem Typ machen und dabei @interfaceObject
und dieselbe @key
-Direktive anwenden. Dadurch können Sie jeder Entität, die Ihre Schnittstelle implementiert, neue Felder hinzufügen (z. B. das Feld Reviews
zu allen Product
hinzufügen).
[ Key ( " id " ) ]
[ InterfaceObject ]
public class Product
{
[ ID ]
public string Id { get ; set ; }
public List < string > Reviews { get ; set ; }
}
Die @requiresScopes
-Direktive wird verwendet, um anzugeben, dass das Zielelement nur für die authentifizierten Supergraph-Benutzer mit den entsprechenden JWT-Bereichen zugänglich ist. Weitere Einzelheiten finden Sie im Artikel zum 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 ) ) ;
}
Dadurch wird das folgende Schema generiert
type Query {
product ( id : ID ! ): Product @requiresScopes ( scopes : [ [ " scope1, scope2 " , " scope3 " ], [ " scope4 " ] ])
}
Sie können die @contact
Direktive verwenden, um die Kontaktinformationen Ihres Teams zu einem Subgraph-Schema hinzuzufügen. Diese Informationen werden in Studio angezeigt, sodass andere Teams wissen, an wen sie sich wenden können, wenn sie Hilfe beim Untergraphen benötigen. Einzelheiten finden Sie in der Dokumentation.
Wir müssen das Attribut [Contact]
auf ein Schema anwenden. Sie können entweder das Attribut [Contact]
auf ein benutzerdefiniertes Schema anwenden und Ihr benutzerdefiniertes Schema an die AddApolloFederationV2
Erweiterung übergeben.
[ 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
;
Oder wenden Sie @contact
Direktive direkt auf ein Schema an, indem Sie eine benutzerdefinierte Schemakonfigurationsaktion bereitstellen
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
verwendet standardmäßig automatisch den Namen des Query
. Wenn Sie benutzerdefinierte Query
Operationstypen verwenden, müssen Sie das Schema explizit mit diesen benutzerdefinierten Werten konfigurieren.
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 ( ) ;
Die Migration von HotChocolate.Federation
zu ApolloGraphQL.HotChocolate.Federation
ist einfach. Aktualisieren Sie einfach Ihren Paketimport, um auf ein neues Modul zu verweisen
- +
und Namespace-Importe aktualisieren
- using HotChocolate.ApolloFederation;
+ using ApolloGraphQL.HotChocolate.Federation;
Während wir versuchten, den Migrationsprozess so reibungslos wie möglich zu gestalten, mussten wir einige Änderungen an der Bibliothek vornehmen. Aufgrund der Abhängigkeit von einigen internen APIs mussten wir folgende bahnbrechende Änderungen an der Bibliothek vornehmen:
[Key]
ist jetzt nur auf Klassen anwendbar und kann nicht mehr auf einzelne Felder angewendet werden[ReferenceResolver]
ist jetzt nur auf öffentliche statische Methoden innerhalb einer Entität anwendbar, es ist nicht mehr auf Klassen anwendbar [EntityResolver]
s können die Entitätsdarstellung automatisch den unterstützten @key
/ @requires
-Werten zuordnen. Skalare @key
-Felder werden automatisch zugeordnet und wir können das Attribut [Map]
verwenden, um Skalarwerte aus komplexen Auswahlsätzen automatisch zuzuordnen.
Derzeit unterstützen wir keine automatische Zuordnung von Listen- und Objektwerten.
Um dieses Problem zu umgehen, müssen Sie das Darstellungsobjekt in Ihrer Implementierung manuell analysieren.
[ ReferenceResolver ]
public static Foo GetByFooBar (
[ LocalState ] ObjectValueNode data
Data repository )
{
// TODO implement logic here by manually reading values from local state data
}
@link
UnterstützungDerzeit unterstützen wir nur den Import von Elementen aus den referenzierten Untergraphen.
Das Benennen von Namensräumen und Umbenennen von Elementen wird derzeit nicht unterstützt. Weitere Informationen finden Sie im Problem.
Wenn Sie eine spezielle Frage zur Bibliothek oder zum Code haben, starten Sie bitte eine Diskussion in den Apollo-Community-Foren oder starten Sie eine Unterhaltung auf unserem Discord-Server.
Um zu beginnen, forken Sie bitte das Repo und checken Sie einen neuen Zweig aus. Anschließend können Sie die Bibliothek lokal erstellen, indem Sie sie ausführen
# install dependencies
dotnet restore
# build project
dotnet build
# run tests
dotnet test
Weitere Informationen finden Sie unter CONTRIBUTING.md.
Nachdem Sie Ihre lokale Niederlassung eingerichtet haben, werfen Sie einen Blick auf unsere offenen Fragen, um zu sehen, wo Sie einen Beitrag leisten können.
Weitere Informationen dazu, wie Sie das Team bei Sicherheitsproblemen kontaktieren können, finden Sie in unserer Sicherheitsrichtlinie.
Diese Bibliothek ist unter der MIT-Lizenz (MIT) lizenziert.