Set of scripts and helper utilities to extend Ariadne GraphQL library
pip install ariadne-extensions
Support for Federation Specification
- Generate federation schema types and directives (
_Any,_FieldSet, ...) - Implements
{_service{sdl}}query - Detects boundary types and generates
_Entitiesunion - Implements resolve reference helpers for boundary types queried over
{_entities}query (resolve_referenceandresolve_referencesdecorators)
FederatedManager is a class responsible for creating and executable schema that complies with Federation Specification. Similar to what make_executable_schema does with ordinary schema file.
Create a FederatedManager instance passing in path to your schema file and QueryType instance. Manager needs to query_type to register _entities and _service resolvers.
query_type = QueryType()
manager = federation.FederatedManager(
schema_sdl_file='/some/path/schema.graphql',
query=query_type,
)Register any other ObjectTypes and resolvers by either calling and add_types method, or by extending manager.types list.
photo_type = ObjectType('Photo')
thumbnail_type = ObjectType('Thumbnail')
manager.add_types(photo_type, thumbnail_type)
manager.types.append(snake_case_fallback_resolvers)Finally, get a combiled schema. This compiled schema will extend types defined in '/some/path/schema.graphql' with directives, types and queries, that required by Federation Specification protocol.
schema = manager.get_schema()If you are using GraphQL Federation, your service schema probably implements some so called "boundary objects". That's where FederatedObjectType is useful.
FederatedObjectType implements resolve_reference and resolve_references decorator. Those are used to register functions, that will be called when a federation gateway calls {_entities{}} query.
Let's say User is a boundary type, with a single id key. You need to implement a function, that will accept a dictionary of keys ({'id': ...} in our example) and return a User instance.
FederatedManager will call this function for every _entities([{__typename: 'User', id: ...}]) query.
user_type = federation.FederatedObjectType('User')
@user_type.resolve_reference
def resolve_user_reference(representation, obj, info):
user_id = representation.get('id')
return get_user_by_id(user_id)FederatedObjectType extends Ariadne's ObjectType. You can still use the field decorator, set_alias method and others as in regular ObjectType, and others.
@user_type.field('name')
def resolve_billing_account(obj, *_, id):
return f'{obj.first_name} {obj_last_name}'Don't forget to add user_type to our manager.
manager.add_types(user_type)type User @key(fields: "id") @extends {
id: ID! @external
photos: [Photo]!
}
type Photo {
id: ID!
url: String!
description: String
}
from os.path import dirname, join
from ariadne import QueryType, ObjectType, snake_case_fallback_resolvers
from ariadne_extensions import federation
query_type = QueryType()
manager = federation.FederatedManager(
schema_sdl_file=join(dirname(__file__), 'schema.graphql'),
query=query_type,
)
user_type = federation.FederatedObjectType('User')
photo_type = ObjectType('Photo')
@user_type.resolve_reference
def resolve_user_reference(representation, obj, info):
user_id = representation.get('id')
return get_user_by_id(user_id)
@user_type.field('name')
def resolve_billing_account(obj, *_, id):
return f'{obj.first_name} {obj_last_name}'
manager.add_types(user_type, photo_type)
manager.add_types(snake_case_fallback_resolvers)
schema = manager.get_schema()