HotChocolate.ApolloFederation . تدعم حزمة ApolloFederation الآن Union v2 بشكل كامل. من أجل تبسيط عمليات التكامل في النظام البيئي لـ HC، قررنا إيقاف هذه الحزمة لصالح دعم حزمة مدمجة واحدة كاملة الميزات.تحذير نظرًا لحدوث تغيير جذري في واجهة برمجة التطبيقات العامة، لا يمكننا دعم الإصدارات الأحدث من
HotChocolateحتى تكتمل واجهة برمجة التطبيقات البديلة الخاصة بها (العمل حاليًا قيد التقدم). يمكننا فقط دعم الإصدارات v13.5.xوv13.6.x
يعد Apollo Union عبارة عن بنية قوية ومفتوحة تساعدك على إنشاء رسم بياني فائق موحد يجمع بين واجهات برمجة تطبيقات GraphQL المتعددة. يوفر ApolloGraphQL.HotChocolate.Federation دعم اتحاد Apollo لإنشاء رسوم بيانية فرعية في نظام HotChocolate البيئي. يمكن تشغيل الرسوم البيانية الفرعية الفردية بشكل مستقل عن بعضها البعض، ولكن يمكن أيضًا تحديد العلاقات مع الرسوم البيانية الفرعية الأخرى باستخدام التوجيهات الموحدة. راجع وثائق اتحاد أبولو للحصول على التفاصيل.
تم نشر حزمة 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 Union في خدمة GraphQL الخاصة بك.
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services
. AddGraphQLServer ( )
. AddApolloFederationV2 ( )
// register your types and services
;
var app = builder . Build ( ) ;
app . MapGraphQL ( ) ;
app . Run ( ) ;إذا كنت ترغب في الاشتراك في مخطط الاتحاد v1، فستحتاج إلى استخدام ملحق
.AddApolloFederation()بدلاً من ذلك.
ارجع إلى وثائق HotChocolate للحصول على معلومات تفصيلية حول كيفية إنشاء مخططات GraphQL وتكوين الخادم الخاص بك.
يتطلب اتحاد أبولو من الرسوم البيانية الفرعية توفير بعض البيانات الوصفية الإضافية لجعلها على علم بالرسم البياني الفائق. الكيانات هي كائنات GraphQL التي يمكن تعريفها بشكل فريد عبر الرسم البياني الفائق بواسطة @key s المحدد. نظرًا لأنه يمكن توسيع الكيانات من خلال رسوم بيانية فرعية مختلفة، فإننا نحتاج إلى نقطة دخول إضافية للوصول إلى الكيانات، أي أن الرسوم البيانية الفرعية تحتاج إلى تنفيذ وحدات الحل المرجعية للكيانات التي تدعمها.
راجع وثائق أبولو للحصول على تفاصيل إضافية عن الاتحاد.
يتم توفير جميع التوجيهات الموحدة كسمات يمكن تطبيقها مباشرة على الفئات/الحقول/الطرق.
[ 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 تطبيقه على الكائنات، راجع وثائق @extendsExternal على الحقول، راجع الوثائق @externalKey المطبق على الكائنات، راجع وثائق @keyProvides على الحقول، راجع @provides الوثائقRequires التطبيق في الحقول، راجع @requires الوثائقتوجيهات الاتحاد v2 (تتضمن جميع توجيهات v1)
ApolloTag قابل للتطبيق على المخطط، راجع وثائق @tagApolloAuthenticated (منذ الإصدار 2.5) ينطبق على التعداد والحقل والواجهة والكائن ووثائق @authenticatedComposeDirective (منذ الإصدار 2.1) المطبق على المخطط، راجع وثائق @composeDirectiveContact المطبقة على المخطط، راجع استخدام @contactInaccessible على كافة تعريفات الأنواع، راجع وثائق @inaccessibleInterfaceObject (منذ الإصدار 2.3) ينطبق على الكائنات، راجع وثائق @interfaceObjectKeyInterface قابل للتطبيق على الواجهات، راجع وثائق @key لواجهة الكيانLink المطبق على المخطط، راجع وثائق @linkRequiresScopes (منذ الإصدار 2.5) ينطبق على التعداد والحقل والواجهة والكائن، وثائق @requiresScopesShareable وقابل للتطبيق على المخطط، راجع وثائق @shareableقرار الكيان
Map قابلة للتطبيق على معلمات أسلوب محلل الكيان، تسمح لك بتعيين وسيطة معقدة لقيمة تمثيل أبسط، على سبيل المثال [Map("foo.bar")] string barReferenceResolver ينطبق على الطرق الثابتة العامة داخل فئة الكيان للإشارة إلى محلل الكيانوبدلاً من ذلك، إذا كنت بحاجة إلى مزيد من التحكم الدقيق، يمكنك استخدام النهج الأول للتعليمات البرمجية وملء معلومات الاتحاد يدويًا في واصف نوع 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 على الكائنات، راجع وثائق @extendsExternal على الحقول، راجع الوثائق @externalKey(fieldset) المطبق على الكائنات، راجع وثائق @keyProvides(fieldset) على الحقول، راجع وثائق @providesRequires(fieldset) المطبقة على الحقول، راجع @requires الوثائقتوجيهات الاتحاد v2 (تتضمن جميع توجيهات v1)
ApolloTag على جميع تعريفات الأنواع، راجع وثائق @tagApolloAuthenticated (منذ الإصدار 2.5) ينطبق على التعداد والحقل والواجهة والكائن ووثائق @authenticatedComposeDirective(name) (منذ الإصدار 2.1) المطبق على المخطط، راجع وثائق @composeDirectiveContact(name, url?, description?) المطبقة على المخطط، راجع استخدام @contactInaccessible على كافة تعريفات الأنواع، راجع وثائق @inaccessibleInterfaceObject (منذ الإصدار 2.3) ينطبق على الكائنات، راجع وثائق @interfaceObjectKey(fieldset) المطبق على الكائنات، راجع وثائق @keyLink(url, [import]?) المطبق على المخطط، راجع وثائق @linkNonResolvableKey(fieldset) ينطبق على الكائنات، راجع وثائق @key غير القابلة للحلRequiresScopes(scopes) (منذ الإصدار 2.5) ينطبق على التعداد والحقل والواجهة والكائن، وثائق @requiresScopesShareable على الحقول والكائنات، راجع وثائق @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 Union 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 Union 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 . يتيح لك ذلك إضافة حقول جديدة إلى كل كيان يقوم بتنفيذ الواجهة الخاصة بك (على سبيل المثال، إضافة حقل Reviews إلى جميع عمليات تنفيذ Product ).
[ 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 لإضافة معلومات الاتصال الخاصة بفريقك إلى مخطط الرسم البياني الفرعي. يتم عرض هذه المعلومات في الاستوديو، مما يساعد الفرق الأخرى على معرفة من يجب الاتصال به للحصول على المساعدة في الرسم البياني الفرعي. انظر الوثائق للحصول على التفاصيل.
نحتاج إلى تطبيق سمة [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;بينما كنا نحاول أن نجعل عملية الترحيل سلسة قدر الإمكان، كان علينا إجراء بعض التعديلات على المكتبة. نظرًا للاعتماد على بعض واجهات برمجة التطبيقات الداخلية، كان علينا إجراء التغييرات العاجلة التالية على المكتبة:
[Key] ينطبق الآن فقط على الفئات ولم يعد بإمكانك تطبيقه على الحقول الفردية[ReferenceResolver] ينطبق الآن فقط على الأساليب الثابتة العامة داخل الكيان ، ولم يعد قابلاً للتطبيق على الفئات يمكن لـ [EntityResolver] تعيين تمثيل الكيان تلقائيًا إلى قيم @key / @requires المدعومة. يتم تعيين حقول Scalars @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.
بعد الانتهاء من إعداد فرعك المحلي، قم بإلقاء نظرة على مشكلاتنا المفتوحة لمعرفة أين يمكنك المساهمة.
لمزيد من المعلومات حول كيفية الاتصال بالفريق بشأن المشكلات الأمنية، راجع سياسة الأمان الخاصة بنا.