Packages
absinthe
1.6.0
1.11.0
1.10.2
1.10.1
1.10.0
1.9.1
1.9.0
1.8.0
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.8
1.6.7
retired
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.6.0-rc.1
1.6.0-rc.0
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.5.0-rc.5
1.5.0-rc.4
1.5.0-rc.3
1.5.0-rc.2
1.5.0-rc.1
1.5.0-rc.0
1.5.0-beta.2
1.5.0-beta.1
1.5.0-beta.0
1.5.0-alpha.4
1.5.0-alpha.3
1.5.0-alpha.2
1.5.0-alpha.1
1.5.0-alpha.0
1.4.16
1.4.15
1.4.14
1.4.13
1.4.12
1.4.11
1.4.10
1.4.9
1.4.8
retired
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.4.0-rc.3
1.4.0-rc.2
1.4.0-rc.1
1.4.0-rc.0
1.4.0-beta.5
1.4.0-beta.4
1.4.0-beta.3
1.4.0-beta.2
1.4.0-beta.1
1.3.2
1.3.1
1.3.0
1.3.0-rc.0
1.3.0-beta.2
1.3.0-beta.1
1.3.0-beta.0
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.2.0-rc.0
1.2.0-beta.0
1.2.0-alpha0
1.2.0-alpha.2
1.2.0-alpha.1
1.1.11
1.1.10
1.1.9
1.1.8
1.1.7
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.0
0.5.2
0.5.1
0.5.0
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.2.3
0.2.2
0.2.1
0.1.0
GraphQL for Elixir
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/absinthe/phase/document/uses.ex
defmodule Absinthe.Phase.Document.Uses do
@moduledoc false
# Tracks uses of:
# - Variables
# - Fragments
use Absinthe.Phase
alias Absinthe.Blueprint
@typep acc_t :: %{
fragments_available: [Blueprint.Document.Fragment.Named.t()],
fragments: [Blueprint.Document.Fragment.Named.Use.t()],
variables: [Blueprint.Input.Variable.Use.t()]
}
@spec run(Blueprint.t(), Keyword.t()) :: {:ok, Blueprint.t()}
def run(input, _options \\ []) do
ops = Enum.map(input.operations, &add_uses(&1, input))
node = %{input | operations: ops}
{:ok, node}
end
@spec add_uses(Blueprint.Document.Operation.t(), Blueprint.t()) ::
Blueprint.Document.Operation.t()
defp add_uses(%Blueprint.Document.Operation{} = node, doc) do
acc = %{
fragments_available: doc.fragments,
fragments: [],
variables: []
}
{_, acc} = Blueprint.prewalk(node, acc, &handle_use/2)
%{
node
| fragment_uses: acc.fragments ++ node.fragment_uses,
variable_uses: acc.variables ++ node.variable_uses
}
end
@spec handle_use(Blueprint.node_t(), acc_t) :: {Blueprint.node_t(), acc_t}
defp handle_use(%Blueprint.Document.Fragment.Spread{} = node, acc) do
if uses?(acc.fragments, node) do
{node, acc}
else
target_fragment = Enum.find(acc.fragments_available, &(&1.name == node.name))
if target_fragment do
acc = acc |> put_use(target_fragment)
{_, acc} = Blueprint.prewalk(target_fragment, acc, &handle_use/2)
{node, acc}
else
{node, acc}
end
end
end
defp handle_use(%Blueprint.Input.Variable{} = node, acc) do
{node, put_use(acc, node)}
end
defp handle_use(node, acc) do
{node, acc}
end
@spec uses?([Blueprint.use_t()], Blueprint.Document.Fragment.Spread.t()) :: boolean
defp uses?(list, node) do
Enum.find(list, &(&1.name == node.name))
end
@spec put_use(acc_t, Blueprint.node_t()) :: acc_t
defp put_use(acc, %Blueprint.Input.Variable{} = node) do
ref = Blueprint.Input.Variable.to_use(node)
update_in(acc.variables, &[ref | &1])
end
defp put_use(acc, %Blueprint.Document.Fragment.Named{} = node) do
ref = Blueprint.Document.Fragment.Named.to_use(node)
update_in(acc.fragments, &[ref | &1])
end
end