@@ -467,7 +467,6 @@ defmodule AshGraphql do
467467 resource ,
468468 all_domains ,
469469 already_checked \\ [ ] ,
470- nested? \\ true ,
471470 return_new_checked? \\ false
472471 ) do
473472 if resource in already_checked do
@@ -479,51 +478,186 @@ defmodule AshGraphql do
479478 else
480479 already_checked = [ resource | already_checked ]
481480
482- resource
483- |> Ash.Resource.Info . public_attributes ( )
484- |> Enum . concat ( all_arguments ( resource , all_domains ) )
485- |> Enum . concat ( Ash.Resource.Info . calculations ( resource ) )
486- |> Enum . concat (
481+ attrs =
487482 resource
488- |> Ash.Resource.Info . actions ( )
489- |> Enum . filter ( & ( & 1 . type == :action && & 1 . returns ) )
490- |> Enum . map ( fn action ->
491- % {
492- type: action . returns ,
493- constraints: action . constraints ,
494- name: action . name ,
495- from_generic_action?: true
496- }
483+ |> Ash.Resource.Info . public_attributes ( )
484+ |> Enum . concat ( all_arguments ( resource , all_domains ) )
485+ |> Enum . concat ( Ash.Resource.Info . calculations ( resource ) )
486+ |> Enum . concat (
487+ resource
488+ |> Ash.Resource.Info . actions ( )
489+ |> Enum . filter ( & ( & 1 . type == :action && & 1 . returns ) )
490+ |> Enum . map ( fn action ->
491+ % {
492+ type: action . returns ,
493+ constraints: action . constraints ,
494+ name: action . name ,
495+ from_generic_action?: true
496+ }
497+ end )
498+ )
499+
500+ { attrs , already_checked } =
501+ Enum . reduce ( attrs , { [ ] , already_checked } , fn
502+ % { type: type } = attr , { attrs , already_checked } ->
503+ constraints = Map . get ( attr , :constraints , [ ] )
504+
505+ { nested , already_checked } =
506+ nested_attrs ( type , all_domains , constraints , already_checked )
507+
508+ nested =
509+ Enum . map ( nested , & Map . put ( & 1 , :original_name , attr . name ) )
510+
511+ { [ attr | nested ] ++ attrs , already_checked }
497512 end )
498- )
499- |> Enum . reduce ( { [ ] , already_checked } , fn % { type: type } = attr , { acc , already_checked } ->
500- if nested? do
501- constraints = Map . get ( attr , :constraints , [ ] )
502513
503- { nested , already_checked } =
504- nested_attrs ( type , all_domains , constraints , already_checked )
514+ { attrs , already_checked } =
515+ Enum . reduce ( attrs , { [ ] , already_checked } , fn attr , { attrs , already_checked } ->
516+ if attr . type in already_checked do
517+ { [ attr | attrs ] , already_checked }
518+ else
519+ { new_attrs , already_checked } =
520+ expand_named_nested_attrs (
521+ Map . put ( attr , :original_name , attr . name ) ,
522+ already_checked
523+ )
524+
525+ { [ attr | new_attrs ++ attrs ] , already_checked }
526+ end
527+ end )
528+
529+ attrs =
530+ Enum . filter ( attrs , fn attr ->
531+ if Map . get ( attr , :from_generic_action? ) do
532+ true
533+ else
534+ AshGraphql.Resource.Info . show_field? (
535+ resource ,
536+ Map . get ( attr , :original_name , attr . name )
537+ )
538+ end
539+ end )
505540
506- { [ attr | nested ] ++ acc , already_checked }
507- else
508- { [ attr | acc ] , already_checked }
541+ if return_new_checked? do
542+ { attrs , already_checked }
543+ else
544+ attrs
545+ end
546+ end
547+ end
548+
549+ defp expand_named_nested_attrs ( % { type: { :array , type } } = attr , already_checked ) do
550+ expand_named_nested_attrs (
551+ % { attr | type: type , constraints: attr . constraints [ :items ] || [ ] } ,
552+ already_checked
553+ )
554+ end
555+
556+ # sobelow_skip ["DOS.BinToAtom"]
557+ defp expand_named_nested_attrs ( % { type: type } = attr , already_checked )
558+ when type in [ Ash.Type.Map , Ash.Type.Struct , Ash.Type.Keyset ] do
559+ Enum . reduce (
560+ attr . constraints [ :fields ] || [ ] ,
561+ { [ ] , already_checked } ,
562+ fn { key , config } , { attrs , already_checked } ->
563+ case config [ :type ] do
564+ { :array , type } ->
565+ fake_attr = % {
566+ attr
567+ | name: :"#{ attr . name } _#{ key } " ,
568+ type: type ,
569+ constraints: config [ :constraints ] [ :items ] || [ ]
570+ }
571+
572+ { new , already_checked } =
573+ expand_named_nested_attrs (
574+ fake_attr ,
575+ already_checked
576+ )
577+
578+ { [ fake_attr | attrs ] ++ new , already_checked }
579+
580+ type ->
581+ fake_attr = % {
582+ attr
583+ | name: :"#{ attr . name } _#{ key } " ,
584+ type: type ,
585+ constraints: config [ :constraints ] || [ ]
586+ }
587+
588+ { new , already_checked } =
589+ expand_named_nested_attrs (
590+ fake_attr ,
591+ already_checked
592+ )
593+
594+ { [ fake_attr | attrs ] ++ new , already_checked }
509595 end
510- end )
511- |> then ( fn { attrs , checked } ->
512- attrs =
513- Enum . filter ( attrs , fn attr ->
514- if Map . get ( attr , :from_generic_action? ) do
515- true
516- else
517- AshGraphql.Resource.Info . show_field? ( resource , attr . name )
518- end
519- end )
596+ end
597+ )
598+ |> then ( fn { attrs , already_checked } ->
599+ { [ attr | attrs ] , already_checked }
600+ end )
601+ end
602+
603+ # sobelow_skip ["DOS.BinToAtom"]
604+ defp expand_named_nested_attrs ( % { type: Ash.Type.Union } = attr , already_checked ) do
605+ Enum . reduce (
606+ attr . constraints [ :types ] || [ ] ,
607+ { [ ] , already_checked } ,
608+ fn { key , config } , { attrs , already_checked } ->
609+ case config [ :type ] do
610+ { :array , type } ->
611+ fake_attr = % {
612+ attr
613+ | name: :"#{ attr . name } _#{ key } " ,
614+ type: type ,
615+ constraints: config [ :constraints ] [ :items ] || [ ]
616+ }
520617
521- if return_new_checked? do
522- { attrs , checked }
523- else
524- attrs
618+ { new , already_checked } =
619+ expand_named_nested_attrs (
620+ fake_attr ,
621+ already_checked
622+ )
623+
624+ { [ fake_attr | attrs ] ++ new , already_checked }
625+
626+ type ->
627+ fake_attr = % {
628+ attr
629+ | name: :"#{ attr . name } _#{ key } " ,
630+ type: type ,
631+ constraints: config [ :constraints ] || [ ]
632+ }
633+
634+ { new , already_checked } =
635+ expand_named_nested_attrs (
636+ fake_attr ,
637+ already_checked
638+ )
639+
640+ { [ fake_attr | attrs ] ++ new , already_checked }
525641 end
526- end )
642+ end
643+ )
644+ |> then ( fn { attrs , already_checked } ->
645+ { [ attr | attrs ] , already_checked }
646+ end )
647+ end
648+
649+ defp expand_named_nested_attrs ( attr , already_checked ) do
650+ if Ash.Type.NewType . new_type? ( attr . type ) and attr . type not in already_checked do
651+ constraints = Ash.Type.NewType . constraints ( attr . type , attr . constraints )
652+
653+ already_checked = [ attr . type | already_checked ]
654+
655+ expand_named_nested_attrs (
656+ % { attr | type: Ash.Type.NewType . subtype_of ( attr . type ) , constraints: constraints } ,
657+ already_checked
658+ )
659+ else
660+ { [ ] , already_checked }
527661 end
528662 end
529663
@@ -604,7 +738,7 @@ defmodule AshGraphql do
604738 AshGraphql.Resource . embedded? ( type ) ->
605739 type
606740 |> unwrap_type ( )
607- |> all_attributes_and_arguments ( all_domains , already_checked , true , true )
741+ |> all_attributes_and_arguments ( all_domains , already_checked , true )
608742
609743 Ash.Type.NewType . new_type? ( type ) ->
610744 constraints = Ash.Type.NewType . constraints ( type , constraints )
0 commit comments