From 892b3adad8caf14d286f9a20579b5391e0b832af Mon Sep 17 00:00:00 2001 From: Skander Mzali Date: Thu, 31 Jul 2025 17:10:49 -0700 Subject: [PATCH 1/2] Add failing test for a calculation with a :struct return type --- test/read_test.exs | 30 +++++++++++++++++++++++++ test/support/resources/post.ex | 10 +++++++++ test/support/types/unreferenced_type.ex | 13 +++++++++++ 3 files changed, 53 insertions(+) create mode 100644 test/support/types/unreferenced_type.ex diff --git a/test/read_test.exs b/test/read_test.exs index e0ad5c1e..150395e9 100644 --- a/test/read_test.exs +++ b/test/read_test.exs @@ -1625,4 +1625,34 @@ defmodule AshGraphql.ReadTest do } = result end end + + describe "calculations" do + test "loads calculated struct type that uses constraint" do + post = + AshGraphql.Test.Post + |> Ash.Changeset.for_create(:create, + text: "a", + published: true + ) + |> Ash.create!() + + resp = + """ + query postLibrary { + postLibrary(sort: {field: TEXT}) { + structCalc { + some + } + } + } + """ + |> Absinthe.run(AshGraphql.Test.Schema) + + assert {:ok, result} = resp + + refute Map.has_key?(result, :errors) + + assert %{data: %{"postLibrary" => [%{"structCalc" => %{"some" => "string"}}]}} = result + end + end end diff --git a/test/support/resources/post.ex b/test/support/resources/post.ex index 3179ee91..095e4a70 100644 --- a/test/support/resources/post.ex +++ b/test/support/resources/post.ex @@ -625,6 +625,16 @@ defmodule AshGraphql.Test.Post do end, public?: true ) + + calculate( + :struct_calc, + :struct, + fn records, _ -> + Enum.map(records, fn _ -> %{some: "string"} end) + end, + public?: true, + constraints: [instance_of: AshGraphql.Test.UnreferencedType] + ) end aggregates do diff --git a/test/support/types/unreferenced_type.ex b/test/support/types/unreferenced_type.ex new file mode 100644 index 00000000..1232001f --- /dev/null +++ b/test/support/types/unreferenced_type.ex @@ -0,0 +1,13 @@ +defmodule AshGraphql.Test.UnreferencedType do + @moduledoc false + use Ash.Type.NewType, + subtype_of: :map, + constraints: [ + fields: [ + some: [ + type: :string, + allow_nil?: false + ] + ] + ] +end From 8bb77dfebba945fa6d7cc81bf4a2ffe1d40844e0 Mon Sep 17 00:00:00 2001 From: Skander Mzali Date: Thu, 31 Jul 2025 17:58:47 -0700 Subject: [PATCH 2/2] chore: traverse instance_of in constraints when present (not working yet) --- lib/ash_graphql.ex | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/ash_graphql.ex b/lib/ash_graphql.ex index a64c8039..84f18e13 100644 --- a/lib/ash_graphql.ex +++ b/lib/ash_graphql.ex @@ -748,6 +748,16 @@ defmodule AshGraphql do type = Ash.Type.NewType.subtype_of(type) nested_attrs(type, all_domains, constraints, already_checked) + type == Ash.Type.Struct && Keyword.has_key?(constraints, :instance_of) -> + type = Keyword.get(constraints, :instance_of) + + if function_exported?(type, :subtype_constraints, 0) do + constraints = apply(type, :subtype_constraints, []) + nested_attrs(type, all_domains, constraints, already_checked) + else + {[], already_checked} + end + true -> {[], already_checked} end