Packages
absinthe
0.2.1
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
Current section
Files
Jump to
Current section
Files
lib/absinthe/execution/resolution/field.ex
defimpl Absinthe.Execution.Resolution, for: Absinthe.Language.Field do
alias Absinthe.Execution
alias Absinthe.Execution.Resolution
alias Absinthe.Type
alias Absinthe.Flag
@spec resolve(Absinthe.Language.Field.t,
Absinthe.Execution.t) :: {:ok, map} | {:error, any}
def resolve(%{name: name} = ast_node, %{strategy: :serial, resolution: %{parent_type: parent_type, target: target}} = execution) do
field = Type.field(parent_type, ast_node.name)
if field do
case field do
%{resolve: nil} ->
target |> Map.get(name |> String.to_atom) |> result(ast_node, field, execution)
%{resolve: resolver} ->
case Execution.Arguments.build(ast_node, field.args, execution) do
{:ok, args, exe} ->
resolver.(args, exe)
|> process_raw_result(ast_node, field, exe)
{:error, {missing, invalid}, exe} ->
exe
|> skip_as(:missing, missing, name, ast_node)
|> skip_as(:invalid, invalid, name, ast_node)
|> Flag.as(:skip)
end
end
else
execution
|> Execution.put_error(:field, ast_node.name, "Not present in schema", at: ast_node)
|> Flag.as(:skip)
end
end
defp skip_as(execution, _reason, [], _name, _ast_node) do
execution
end
defp skip_as(execution, reason, collected, name, ast_node) do
execution
|> Execution.put_error(:field, name, describe(collected, reason), at: ast_node)
end
@reasons %{missing: %{prefix: "required argument", suffix: "not provided"},
invalid: %{prefix: "badly formed argument", suffix: "provided"}}
# Generate a detailed error message for a list of missing arguments
@spec describe([binary], atom) :: binary
defp describe(collected, reason) do
{msg, listing} = do_describe(collected, reason)
msg <> " (" <> listing <> ") " <> @reasons[reason].suffix
end
# Determine the error message parts
@spec do_describe([binary], :atom) :: {binary, binary}
defp do_describe(collected, reason) do
quote_it = &"`#{&1}'"
prefix = @reasons[reason].prefix
case collected do
[item] -> {"1 #{prefix}", quote_it.(item)}
_ -> {"#{length(collected)} #{prefix}s", collected |> Enum.map(quote_it) |> Enum.join(", ")}
end
end
defp process_raw_result({:ok, value}, ast_node, field, execution) do
exe_with_deprecation = add_field_deprecation(execution, field, ast_node)
value
|> result(ast_node, field, exe_with_deprecation)
end
defp process_raw_result({:error, errors}, ast_node, field, execution) do
errors
|> List.wrap
|> Enum.reduce(execution, fn
value, exe -> Execution.put_error(exe, :field, ast_node.name, value, at: ast_node)
end)
|> add_field_deprecation(field, ast_node)
|> Flag.as(:skip)
end
defp process_raw_result(_other, ast_node, field, execution) do
execution
|> add_field_deprecation(field, ast_node)
|> Execution.put_error(:field, ast_node.name, "Did not resolve to match {:ok, _} or {:error, _}", at: ast_node)
|> Flag.as(:skip)
end
defp add_field_deprecation(execution, %{deprecation: nil}, _ast_node) do
execution
end
defp add_field_deprecation(execution, %{name: name, deprecation: %{reason: reason}}, ast_node) do
details = if reason, do: "; #{reason}", else: ""
execution
|> Execution.put_error(:field, name, "Deprecated" <> details, at: ast_node)
end
defp result(nil, _ast_node, _field, execution) do
{:ok, nil, execution}
end
defp result(value, ast_node, field, execution) do
resolved_type = Type.resolve_type(field.type, value)
next_resolution = %Resolution{type: resolved_type, ast_node: ast_node, target: value}
Resolution.resolve(resolved_type, %{execution | resolution: next_resolution})
end
end