zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

mark_referenced.ex (4142B)


      1 defmodule Absinthe.Phase.Schema.MarkReferenced do
      2   @moduledoc false
      3 
      4   use Absinthe.Phase
      5 
      6   alias Absinthe.Blueprint.{Schema, TypeReference}
      7 
      8   def run(blueprint, _opts) do
      9     %{schema_definitions: [schema]} = blueprint
     10 
     11     schema =
     12       Map.update!(schema, :type_definitions, &mark_referenced(&1, schema.directive_definitions))
     13 
     14     {:ok, %{blueprint | schema_definitions: [schema]}}
     15   end
     16 
     17   @roots [:query, :mutation, :subscription]
     18   defp mark_referenced(type_defs, directive_defs) do
     19     types_by_ref =
     20       Enum.reduce(type_defs, %{}, fn type_def, acc ->
     21         acc
     22         |> Map.put(type_def.identifier, type_def)
     23         |> Map.put(type_def.name, type_def)
     24       end)
     25 
     26     referenced_type_ids =
     27       @roots
     28       |> Enum.map(&Map.get(types_by_ref, &1))
     29       |> Enum.reject(&is_nil/1)
     30       |> Enum.concat(directive_defs)
     31       |> Enum.reduce(MapSet.new(), &referenced_types(&1, types_by_ref, &2))
     32 
     33     for type <- type_defs do
     34       if type.identifier in referenced_type_ids do
     35         put_in(type.__private__[:__absinthe_referenced__], true)
     36       else
     37         type
     38       end
     39     end
     40   end
     41 
     42   defp referenced_types(%Schema.InputValueDefinition{type: type}, types, acc) do
     43     referenced_types(type, types, acc)
     44   end
     45 
     46   defp referenced_types(%Schema.DirectiveDefinition{} = type, types, acc) do
     47     type.arguments
     48     |> Enum.reduce(acc, &referenced_types(&1, types, &2))
     49   end
     50 
     51   defp referenced_types(%Schema.EnumTypeDefinition{identifier: identifier}, _types, acc) do
     52     MapSet.put(acc, identifier)
     53   end
     54 
     55   defp referenced_types(%Schema.FieldDefinition{} = field, types, acc) do
     56     acc =
     57       field.arguments
     58       |> Enum.reduce(acc, &referenced_types(&1, types, &2))
     59 
     60     referenced_types(field.type, types, acc)
     61   end
     62 
     63   defp referenced_types(
     64          %Schema.InputObjectTypeDefinition{identifier: identifier} = input_object,
     65          types,
     66          acc
     67        ) do
     68     if identifier in acc do
     69       acc
     70     else
     71       acc = MapSet.put(acc, identifier)
     72 
     73       input_object.fields
     74       |> Enum.reduce(acc, &referenced_types(&1, types, &2))
     75     end
     76   end
     77 
     78   defp referenced_types(
     79          %Schema.InterfaceTypeDefinition{identifier: identifier} = interface,
     80          schema,
     81          acc
     82        ) do
     83     if identifier in acc do
     84       acc
     85     else
     86       acc = MapSet.put(acc, identifier)
     87 
     88       acc =
     89         interface
     90         |> Schema.InterfaceTypeDefinition.find_implementors(Map.values(schema))
     91         |> Enum.reduce(acc, &referenced_types(&1, schema, &2))
     92 
     93       interface.fields
     94       |> Enum.reduce(acc, &referenced_types(&1, schema, &2))
     95     end
     96   end
     97 
     98   defp referenced_types(%TypeReference.List{of_type: inner_type}, schema, acc) do
     99     referenced_types(inner_type, schema, acc)
    100   end
    101 
    102   defp referenced_types(%TypeReference.NonNull{of_type: inner_type}, schema, acc) do
    103     referenced_types(inner_type, schema, acc)
    104   end
    105 
    106   defp referenced_types(
    107          %Schema.ObjectTypeDefinition{identifier: identifier} = object,
    108          schema,
    109          acc
    110        ) do
    111     if identifier in acc do
    112       acc
    113     else
    114       acc = MapSet.put(acc, identifier)
    115 
    116       acc =
    117         object.fields
    118         |> Enum.reduce(acc, &referenced_types(&1, schema, &2))
    119 
    120       object.interfaces
    121       |> Enum.reduce(acc, &referenced_types(&1, schema, &2))
    122     end
    123   end
    124 
    125   defp referenced_types(%Schema.ScalarTypeDefinition{identifier: identifier}, _schema, acc) do
    126     MapSet.put(acc, identifier)
    127   end
    128 
    129   defp referenced_types(%Schema.UnionTypeDefinition{identifier: identifier} = union, schema, acc) do
    130     if identifier in acc do
    131       acc
    132     else
    133       acc = MapSet.put(acc, identifier)
    134 
    135       union.types
    136       |> Enum.reduce(acc, &referenced_types(&1, schema, &2))
    137     end
    138   end
    139 
    140   defp referenced_types(%TypeReference.Identifier{} = ref, schema, acc) do
    141     referenced_types(Map.fetch!(schema, ref.id), schema, acc)
    142   end
    143 
    144   defp referenced_types(%TypeReference.Name{} = ref, schema, acc) do
    145     referenced_types(Map.fetch!(schema, ref.name), schema, acc)
    146   end
    147 
    148   defp referenced_types(type, schema, acc) when is_atom(type) and type != nil do
    149     referenced_types(Map.fetch!(schema, type), schema, acc)
    150   end
    151 end