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/variables.ex
defmodule Absinthe.Execution.Variables do
# Handles the logic around building and validating variable values for an
# execution.
@moduledoc false
alias Absinthe.Type
alias Absinthe.Language
alias Absinthe.Execution
alias Absinthe.Schema
# Build a variables map from the variable definitions in the selected operation
# and the variable values provided to the execution.
@doc false
@spec build(Execution.t) :: {%{binary => any}, Execution.t}
def build(execution) do
execution.selected_operation.variable_definitions
|> Enum.reduce({%{}, execution |> normalize_keys}, &parse/2)
end
# Normalize the variable keys to binaries
@spec normalize_keys(Execution.t) :: Execution.t
defp normalize_keys(execution) do
%{execution | variables: execution.variables |> Execution.stringify_keys}
end
# Parse a definition and add values/errors
@spec parse(Language.VariableDefinition.t, {map, Execution.t}) :: {map, Execution.t}
defp parse(definition, {_, execution} = acc) do
name = definition.variable.name
ast_type = definition.type |> Language.unwrap
schema_type = Schema.type_from_ast(execution.schema, definition.type)
do_parse(name, definition, ast_type, schema_type, acc)
end
# No schema type was found
@spec do_parse(atom, Language.VariableDefinition.t, Language.NamedType.t, Type.input_t, {map, Execution.t}) :: {map, Execution.t}
defp do_parse(name, _definition, ast_type, nil, {values, execution}) do
exe = execution
|> Execution.put_error(:variable, name, "Type (#{ast_type.name}) not present in schema", at: ast_type )
{values, exe}
end
defp do_parse(name, definition, ast_type, schema_type, {_, execution} = acc) do
default_value = default(definition.default_value)
provided_value = execution.variables |> Map.get(name |> to_string)
value = provided_value || default_value
case Type.valid_input?(schema_type, value) do
true ->
valid(name, value, schema_type, acc)
false ->
invalid(name, value, ast_type, schema_type, acc)
end
end
# Accumulate the value for a valid variable
@spec valid(atom, any, Type.input_t, {map, Execution.t}) :: {map, Execution.t}
defp valid(name, value, schema_type, {values, execution}) do
{
values |> Map.put(to_string(name), coerce(value, schema_type)),
execution
}
end
# Accumulate an error for an invalid variable
@spec invalid(atom, any, Language.NamedType.t, Type.input_t, {map, Execution.t}) :: {map, Execution.t}
defp invalid(name, value, ast_type, _schema_type, {values, execution}) do
exe = execution
|> Execution.put_error(:variable, name, error_message(ast_type, value), at: ast_type)
{values, exe}
end
# Define the error message for an invalid variable
@spec error_message(Language.NamedType.t, any) :: (binary -> binary)
defp error_message(ast_type, nil) do
&"Variable `#{&1}' (#{ast_type.name}): Not provided"
end
defp error_message(ast_type, _value) do
&"Variable `#{&1}' (#{ast_type.name}): Invalid value"
end
# Coerce a value or default provided for a variable so it is suitable for
# the defined type
@spec coerce(any, Type.input_t) :: any
defp coerce(nil, _schema_type) do
nil
end
defp coerce(value, schema_type) do
%{parse: parser} = schema_type |> Type.unwrap
case parser.(value) do
{:ok, coerced} -> coerced
:error -> nil
end
end
# Extract the default value, if any
@spec default(Absinthe.Language.value_t) :: any
defp default(%{value: value}), do: value
defp default(_), do: nil
end