diff --git a/docs/changelog/changes_08.rst b/docs/changelog/changes_08.rst index ddcc2ce..34d1bd5 100644 --- a/docs/changelog/changes_08.rst +++ b/docs/changelog/changes_08.rst @@ -6,7 +6,7 @@ Changes in 0.8 - Introduce ``Schema`` . This is a new high-level api with aim to provide single entrypoint for validation/execution and query/mutations. Previously we had to manage two serapate graphs - one for Query other for Mutation or use `endpoint` - api but ``endpoint`` api is more like an integration-like api for http handlers. + api but ``endpoint`` api is more like an integration-like api for http handlers. More on that in :ref:`Schema docs `. - ``Schema`` returns ``ExecutionResult`` dataclass with ``data``, ``errors`` and ``result`` fields. ``data`` already denormalized but access to `Proxy` object at ``result`` field is retained. - ``Endpoint`` now is much simpler under the hood and it basically delegates execution to schema, only providing support for batching. - Drop custom ``validate`` function for federation since we now have better support for ``_entities`` and ``_service`` fields and their corresponding types. @@ -25,6 +25,21 @@ Changes in 0.8 - Drop ``GraphQLError.errors`` field. Earlier we used to store multiple errors in single ``GraphQLError`` but now its one message - one ``GraphQLError``. - Add ``GraphQLError.message`` field - Dropped support for ``Python 3.7``, which ended support on 2023-06-27 +- Fix: now it is possible to alias record field: + + .. code-block:: python + + Graph([Root([Field("user", TypeRef["User"]))], data_types={"User": Record[{"id": Integer, "name": String}]}) + + .. code-block:: graphql + + query { + user { + id + my_name: name + } + } + Backward-incompatible changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/hiku/denormalize/base.py b/hiku/denormalize/base.py index 1bca35d..3cce98d 100644 --- a/hiku/denormalize/base.py +++ b/hiku/denormalize/base.py @@ -111,7 +111,10 @@ def visit_field(self, obj: Field) -> None: else: # Record type itself does not have custom serialization # TODO: support Scalar/Enum types in Record - self._res[-1][obj.result_key] = self._data[-1][obj.result_key] + + # if record field is aliased, use index_key as a result-key + result_key = obj.result_key if obj.alias is None else obj.index_key + self._res[-1][obj.result_key] = self._data[-1][result_key] def visit_link(self, obj: Link) -> None: if isinstance(self._type[-1], (Union, Interface)): diff --git a/tests/test_endpoint_graphql.py b/tests/test_endpoint_graphql.py index b507621..d47414b 100644 --- a/tests/test_endpoint_graphql.py +++ b/tests/test_endpoint_graphql.py @@ -12,6 +12,8 @@ from hiku.graph import Field, Graph, Root from hiku.schema import Schema from hiku.types import String +from hiku.types import Record +from hiku.types import TypeRef @pytest.fixture(name="sync_graph") @@ -123,3 +125,18 @@ def get_custom_context(ec): {"data": {"answer": "52"}}, {"data": {"__typename": "Query"}}, ] + + +@pytest.mark.asyncio +async def test_denormalize_aliased_record_field(): + async def answer(fields): + return [{"answer": "42"} for _ in fields] + + dt = {"Answer": Record[{"answer": String}]} + graph = Graph( + [Root([Field("question", TypeRef["Answer"], answer)])], data_types=dt + ) + + schema = Schema(AsyncIOExecutor(), graph) + result = await schema.execute("{ question { my_answer: answer } }") + assert result.data == {"question": {"my_answer": "42"}}