zf

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

no_interface_cycles.ex (1794B)


      1 defmodule Absinthe.Phase.Schema.Validation.NoInterfaceCyles do
      2   @moduledoc false
      3 
      4   use Absinthe.Phase
      5   alias Absinthe.Blueprint
      6   alias Absinthe.Blueprint.Schema
      7 
      8   def run(blueprint, _opts) do
      9     blueprint = check(blueprint)
     10 
     11     {:ok, blueprint}
     12   end
     13 
     14   defp check(blueprint) do
     15     graph = :digraph.new([:cyclic])
     16 
     17     try do
     18       _ = build_interface_graph(blueprint, graph)
     19 
     20       Blueprint.prewalk(blueprint, &validate_schema(&1, graph))
     21     after
     22       :digraph.delete(graph)
     23     end
     24   end
     25 
     26   defp validate_schema(%Schema.InterfaceTypeDefinition{} = interface, graph) do
     27     if cycle = :digraph.get_cycle(graph, interface.identifier) do
     28       interface |> put_error(error(interface, cycle))
     29     else
     30       interface
     31     end
     32   end
     33 
     34   defp validate_schema(node, _graph) do
     35     node
     36   end
     37 
     38   defp build_interface_graph(blueprint, graph) do
     39     _ = Blueprint.prewalk(blueprint, &vertex(&1, graph))
     40   end
     41 
     42   defp vertex(%Schema.InterfaceTypeDefinition{} = implementor, graph) do
     43     :digraph.add_vertex(graph, implementor.identifier)
     44 
     45     for interface <- implementor.interfaces do
     46       edge(implementor, interface, graph)
     47     end
     48 
     49     implementor
     50   end
     51 
     52   defp vertex(implementor, _graph) do
     53     implementor
     54   end
     55 
     56   # Add an edge, modeling the relationship between two interfaces
     57   defp edge(implementor, interface, graph) do
     58     :digraph.add_vertex(graph, interface)
     59 
     60     :digraph.add_edge(graph, implementor.identifier, interface)
     61 
     62     true
     63   end
     64 
     65   defp error(type, deps) do
     66     %Absinthe.Phase.Error{
     67       message:
     68         String.trim("""
     69         Interface Cycle Error
     70 
     71         Interface `#{type.identifier}' forms a cycle via: (#{inspect(deps)})
     72         """),
     73       locations: [type.__reference__.location],
     74       phase: __MODULE__,
     75       extra: type.identifier
     76     }
     77   end
     78 end