Skip to content

Commit

Permalink
feat: support @external on OBJECT type
Browse files Browse the repository at this point in the history
  • Loading branch information
mak626 committed Jan 10, 2024
1 parent 8639fea commit a25e2a3
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 3 deletions.
23 changes: 22 additions & 1 deletion graphene_federation/external.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from graphene import Schema
from graphene.types.objecttype import ObjectTypeMeta

from graphene_federation.utils import get_attributed_fields

Expand All @@ -7,7 +8,10 @@ def external(field):
"""
Mark a field as external.
"""
field._external = True
if isinstance(field, ObjectTypeMeta):
field._external_entity = True
else:
field._external = True
return field


Expand All @@ -18,3 +22,20 @@ def get_external_fields(schema: Schema) -> dict:
the `@external` decorator adds a `_external` attribute to them.
"""
return get_attributed_fields(attribute="_external", schema=schema)


def get_external_object_types(schema: Schema) -> dict:
"""
Find all the extended object types from the schema.
They can be easily distinguished from the other type as
the `@external` decorator adds a `_external_entity` attribute to them.
"""
fields = {}

for type_name, type_ in schema.graphql_schema.type_map.items():
if hasattr(type_, "graphene_type") and hasattr(
type_.graphene_type, "_external_entity"
):
fields[type_name] = type_

return fields
11 changes: 9 additions & 2 deletions graphene_federation/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from graphql import GraphQLInterfaceType, GraphQLObjectType

from .compose_directive import is_composable, compose_directive_schema_extensions
from .external import get_external_fields
from .external import get_external_fields, get_external_object_types
from .inaccessible import get_inaccessible_types, get_inaccessible_fields
from .override import get_override_fields
from .requires import get_required_fields
Expand Down Expand Up @@ -134,6 +134,7 @@ def get_sdl(schema: Schema) -> str:
entities = get_entities(schema)
required_fields = get_required_fields(schema)
external_fields = get_external_fields(schema)
external_object_types = get_external_object_types(schema)
override_fields = get_override_fields(schema)

schema_extensions = []
Expand All @@ -147,7 +148,7 @@ def get_sdl(schema: Schema) -> str:

federation_spec_import = []

if extended_types:
if extended_types or external_object_types:
federation_spec_import.append('"@extends"')
if external_fields:
federation_spec_import.append('"@external"')
Expand Down Expand Up @@ -244,6 +245,12 @@ def get_sdl(schema: Schema) -> str:
string_schema = pattern.sub(repl_str, string_schema)

if schema.federation_version >= 2:
# Add `@external` keyword to the type definition of external object types
for object_type_name, _ in external_object_types.items():
type_def = re.compile(rf"type {object_type_name} ([^{{]*)")
repl_str = rf"type {object_type_name} @external \1"
string_schema = type_def.sub(repl_str, string_schema)

for type_name, type in shareable_types.items():
# noinspection PyProtectedMember
if isinstance(type._meta, UnionOptions):
Expand Down

0 comments on commit a25e2a3

Please sign in to comment.