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
_Entities
union - Implements resolve reference helpers for boundary types queried over
{_entities}
query (resolve_reference
andresolve_references
decorators)
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 ObjectType
s 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()