@@ -3227,8 +3227,9 @@ defmodule AshGraphql.Resource do
32273227
32283228 def map_definitions ( resource , all_domains , schema , env ) do
32293229 if AshGraphql.Resource.Info . type ( resource ) do
3230- resource
3231- |> global_maps ( all_domains )
3230+ maps = global_maps ( resource , all_domains )
3231+
3232+ maps
32323233 |> Enum . flat_map ( fn attribute ->
32333234 type_name =
32343235 if function_exported? ( attribute . type , :graphql_type , 1 ) do
@@ -3251,14 +3252,12 @@ defmodule AshGraphql.Resource do
32513252 [ ]
32523253 end
32533254
3254- [
3255- type_name
3256- ]
3257- |> define_map_types ( description , constraints , schema , resource , env , already_checked )
3258- |> Enum . concat (
3259- [
3260- input_type_name
3261- ]
3255+ output_types =
3256+ [ type_name ]
3257+ |> define_map_types ( description , constraints , schema , resource , env , already_checked )
3258+
3259+ input_types =
3260+ [ input_type_name ]
32623261 |> define_input_map_types (
32633262 description ,
32643263 constraints ,
@@ -3267,7 +3266,10 @@ defmodule AshGraphql.Resource do
32673266 env ,
32683267 already_checked
32693268 )
3270- )
3269+
3270+ all_types = output_types ++ input_types
3271+
3272+ all_types
32713273 end )
32723274 else
32733275 [ ]
@@ -3791,14 +3793,72 @@ defmodule AshGraphql.Resource do
37913793
37923794 @ doc false
37933795 def global_maps ( resource , all_domains ) do
3794- resource
3795- |> AshGraphql . all_attributes_and_arguments ( all_domains )
3796- |> Enum . map ( & unnest / 1 )
3797- |> Enum . filter (
3798- & ( Ash.Type.NewType . subtype_of ( & 1 . type ) in [ Ash.Type.Map , Ash.Type.Struct ] &&
3799- ! Enum . empty? ( Ash.Type.NewType . constraints ( & 1 . type , & 1 . constraints ) [ :fields ] || [ ] ) &&
3800- define_type? ( & 1 . type , & 1 . constraints ) )
3801- )
3796+ # Scan direct resource attributes
3797+ direct_types =
3798+ resource
3799+ |> AshGraphql . all_attributes_and_arguments ( all_domains )
3800+ |> Enum . map ( & unnest / 1 )
3801+ |> Enum . filter (
3802+ & ( Ash.Type.NewType . subtype_of ( & 1 . type ) in [ Ash.Type.Map , Ash.Type.Struct ] &&
3803+ ! Enum . empty? ( Ash.Type.NewType . constraints ( & 1 . type , & 1 . constraints ) [ :fields ] || [ ] ) &&
3804+ define_type? ( & 1 . type , & 1 . constraints ) )
3805+ )
3806+
3807+ # Scan union member custom types
3808+ all_attributes = AshGraphql . all_attributes_and_arguments ( resource , all_domains )
3809+ union_member_types = extract_union_member_custom_types ( all_attributes )
3810+
3811+ # Combine and deduplicate
3812+ ( direct_types ++ union_member_types )
3813+ |> Enum . uniq_by ( & { & 1 . type , & 1 . constraints } )
3814+ end
3815+
3816+ defp extract_union_member_custom_types ( attributes ) do
3817+ attributes
3818+ |> Enum . filter ( & is_union_type? / 1 )
3819+ |> Enum . flat_map ( & extract_custom_types_from_union / 1 )
3820+ end
3821+
3822+ defp is_union_type? ( attribute ) do
3823+ type = Ash.Type . get_type ( attribute . type )
3824+
3825+ Ash.Type.NewType . new_type? ( type ) &&
3826+ Ash.Type.NewType . subtype_of ( type ) == Ash.Type.Union
3827+ end
3828+
3829+ defp extract_custom_types_from_union ( union_attribute ) do
3830+ constraints = Ash.Type.NewType . constraints ( union_attribute . type , union_attribute . constraints )
3831+
3832+ constraints [ :types ]
3833+ |> Kernel . || ( [ ] )
3834+ |> Enum . flat_map ( fn { _name , config } ->
3835+ member_type = config [ :type ]
3836+ member_constraints = config [ :constraints ] || [ ]
3837+
3838+ # Create fake attribute for the member type
3839+ fake_attribute = % {
3840+ union_attribute
3841+ | type: member_type ,
3842+ constraints: member_constraints
3843+ }
3844+
3845+ # Check if it's a custom map/struct type that should generate definitions
3846+ if is_custom_map_or_struct_type? ( fake_attribute ) do
3847+ [ fake_attribute ]
3848+ else
3849+ [ ]
3850+ end
3851+ end )
3852+ end
3853+
3854+ defp is_custom_map_or_struct_type? ( attribute ) do
3855+ type = Ash.Type . get_type ( attribute . type )
3856+
3857+ # Check if it's a Map/Struct type with fields AND implements AshGraphql.Type
3858+ Ash.Type.NewType . subtype_of ( type ) in [ Ash.Type.Map , Ash.Type.Struct ] &&
3859+ ! Enum . empty? ( Ash.Type.NewType . constraints ( type , attribute . constraints ) [ :fields ] || [ ] ) &&
3860+ function_exported? ( type , :graphql_type , 1 ) &&
3861+ define_type? ( type , attribute . constraints )
38023862 end
38033863
38043864 @ spec define_type? ( Ash.Type . t ( ) , Ash.Type . constraints ( ) ) :: boolean ( )
0 commit comments