Skip to content

Latest commit

 

History

History
139 lines (93 loc) · 4.55 KB

README.md

File metadata and controls

139 lines (93 loc) · 4.55 KB

Ariadne Extensions

Build Status Coverage Status Unsupported

Set of scripts and helper utilities to extend Ariadne GraphQL library

Install

pip install ariadne-extensions

Features

Federation support

Support for Federation Specification

Features

  1. Generate federation schema types and directives (_Any, _FieldSet, ...)
  2. Implements {_service{sdl}} query
  3. Detects boundary types and generates _Entities union
  4. Implements resolve reference helpers for boundary types queried over {_entities} query (resolve_reference and resolve_references decorators)

Documentation

ariadne_extensions.federation.FederatedManager

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()
ariadne_extensions.federation.FederatedObjectType

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)

Example

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()