Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup Resolution function signatures #3

Merged
merged 6 commits into from
Dec 17, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions lib/ex_graphql/adapter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ defmodule ExGraphQL.Adapter do
end

# Rename a AST node and traverse children
defp load_ast_node(%{__struct__: Language.OperationDefinition, name: name, selection_set: selection_set} = node) do
defp load_ast_node(%Language.OperationDefinition{name: name, selection_set: selection_set} = node) do
%{node | name: name |> to_internal_name(:operation), selection_set: load_ast_node(selection_set)}
end
defp load_ast_node(%{__struct__: Language.SelectionSet, selections: selections} = node) do
defp load_ast_node(%Language.SelectionSet{selections: selections} = node) do
%{node | selections: selections |> Enum.map(&load_ast_node/1)}
end
defp load_ast_node(%{__struct__: Language.Field, arguments: args, name: name, selection_set: selection_set} = node) do
defp load_ast_node(%Language.Field{arguments: args, name: name, selection_set: selection_set} = node) do
%{node | name: name |> to_internal_name(:field), selection_set: load_ast_node(selection_set), arguments: args |> Enum.map(&load_ast_node/1)}
end
defp load_ast_node(%{__struct__: Language.Argument, name: name} = node) do
defp load_ast_node(%Language.Argument{name: name} = node) do
%{node | name: name |> to_internal_name(:argument)}
end
defp load_ast_node(nil) do
Expand Down
15 changes: 8 additions & 7 deletions lib/ex_graphql/execution.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ defmodule ExGraphQL.Execution do
@typedoc "The canonical result representation of an execution"
@type result_t :: %{data: %{binary => any}, errors: [error_t]}

@type t :: %{schema: Type.Schema.t, document: Language.Document.t, variables: map, validate: boolean, selected_operation: ExGraphQL.Type.ObjectType.t, operation_name: atom, errors: [error_t], categorized: boolean, strategy: atom, adapter: atom}
defstruct schema: nil, document: nil, variables: %{}, fragments: %{}, operations: %{}, validate: true, selected_operation: nil, operation_name: nil, errors: [], categorized: false, strategy: nil, adapter: nil
@type t :: %{schema: Type.Schema.t, document: Language.Document.t, variables: map, validate: boolean, selected_operation: ExGraphQL.Type.ObjectType.t, operation_name: atom, errors: [error_t], categorized: boolean, strategy: atom, adapter: atom, resolution: Execution.Resolution.t}
defstruct schema: nil, document: nil, variables: %{}, fragments: %{}, operations: %{}, validate: true, selected_operation: nil, operation_name: nil, errors: [], categorized: false, strategy: nil, adapter: nil, resolution: nil

def run(execution, options \\ []) do
raw = execution |> Map.merge(options |> Enum.into(%{}))
Expand All @@ -28,6 +28,7 @@ defmodule ExGraphQL.Execution do
end
end

@spec prepare(t) :: t
def prepare(execution) do
defined = execution
|> add_configured_adapter
Expand Down Expand Up @@ -76,17 +77,17 @@ defmodule ExGraphQL.Execution do
end

@spec resolve_type(t, t, t) :: t | nil
def resolve_type(target, nil = _child_type, %{__struct__: Type.Union} = parent_type) do
def resolve_type(target, nil = _child_type, %Type.Union{} = parent_type) do
parent_type
|> Type.Union.resolve_type(target)
end
def resolve_type(_target, nil = _child_type, _parent_type) do
nil
end
def resolve_type(_target, %{__struct__: Type.Union} = child_type, parent_type) do
def resolve_type(_target, %Type.Union{} = child_type, parent_type) do
child_type |> Type.Union.member?(parent_type) || nil
end
def resolve_type(target, %{__struct__: Type.InterfaceType} = _child_type, _parent_type) do
def resolve_type(target, %Type.InterfaceType{} = _child_type, _parent_type) do
target
|> Type.InterfaceType.resolve_type
end
Expand Down Expand Up @@ -125,10 +126,10 @@ defmodule ExGraphQL.Execution do
defp categorize_definitions(execution, []) do
execution
end
defp categorize_definitions(%{operations: operations} = execution, [%{__struct__: ExGraphQL.Language.OperationDefinition, name: name} = definition | rest]) do
defp categorize_definitions(%{operations: operations} = execution, [%ExGraphQL.Language.OperationDefinition{name: name} = definition | rest]) do
categorize_definitions(%{execution | operations: operations |> Map.put(name, definition)}, rest)
end
defp categorize_definitions(%{fragments: fragments} = execution, [%{__struct__: ExGraphQL.Language.FragmentDefinition, name: name} = definition | rest]) do
defp categorize_definitions(%{fragments: fragments} = execution, [%ExGraphQL.Language.FragmentDefinition{name: name} = definition | rest]) do
categorize_definitions(%{execution | fragments: fragments |> Map.put(name, definition)}, rest)
end

Expand Down
26 changes: 26 additions & 0 deletions lib/ex_graphql/execution/arguments.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
defmodule ExGraphQL.Execution.Arguments do

alias ExGraphQL.Execution.Literal

def build(ast_arguments, schema_arguments, variables) do
schema_arguments
|> Enum.reduce(%{}, fn ({name, definition}, acc) ->
schema_arg_name = name |> to_string
ast_arg = ast_arguments |> Enum.find(&(&1.name == schema_arg_name))
if ast_arg do
ast_value = if ast_arg.value do
Literal.coerce(definition.type, ast_arg.value, variables)
else
nil
end
variable_value = variables[ast_arg.name]
default_value = definition.default_value
acc
|> Map.put(name, ast_value || variable_value || default_value)
else
acc
end
end)
end

end
40 changes: 40 additions & 0 deletions lib/ex_graphql/execution/literal.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
defmodule ExGraphQL.Execution.Literal do

alias ExGraphQL.Type
alias ExGraphQL.Language

def coerce(input_type, input_value, variables) do
input_type
|> Type.unwrap
|> coerce_unwrapped(input_value, variables)
end

defp coerce_unwrapped(%Type.Scalar{} = scalar, %{value: internal_value}, _variables) do
internal_value
|> scalar.parse_value.()
end
defp coerce_unwrapped(definition_type, %Language.Variable{name: name}, variables) do
variable_value = variables |> Map.get(name)
coerce(definition_type, variable_value, variables)
end
defp coerce_unwrapped(%Type.Scalar{} = scalar, bare, _variables) do
bare
|> to_string
|> scalar.parse_value.()
end

defp coerce_unwrapped(%Type.InputObjectType{fields: thunked_schema_fields}, %{fields: input_fields}, variables) do
schema_fields = thunked_schema_fields |> Type.unthunk
input_fields
|> Enum.reduce(%{}, fn (%{name: name, value: input_value}, acc) ->
case schema_fields |> Map.get(name |> String.to_existing_atom) do
nil -> acc
field -> acc |> Map.put(name |> to_string, coerce(field.type, input_value, variables))
end
end)
end
defp coerce_unwrapped(%Type.Enum{values: enum_values}, %{value: raw_value}, _variables) do
enum_values |> Map.get(raw_value)
end

end
61 changes: 0 additions & 61 deletions lib/ex_graphql/execution/literal_input.ex

This file was deleted.

5 changes: 2 additions & 3 deletions lib/ex_graphql/execution/resolution.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ defprotocol ExGraphQL.Execution.Resolution do
@type t :: %{target: any, parent_type: Type.t, type: Type.t, ast_node: Language.t}
defstruct target: nil, parent_type: nil, type: nil, ast_node: nil

@doc "Returns `true` if `data` is considered blank/empty"
@spec resolve(ExGraphQL.Language.t, ExGraphQL.Execution.Resolution.t, ExGraphQL.Execution.t) :: {:ok, any} | {:error, any}
def resolve(ast_node, resolution, execution)
@spec resolve(ExGraphQL.Language.t, ExGraphQL.Execution.t) :: {:ok, any, ExGraphQL.Execution.t} | {:error, any}
def resolve(ast_node, execution)

end
31 changes: 14 additions & 17 deletions lib/ex_graphql/execution/resolution/field.ex
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
defimpl ExGraphQL.Execution.Resolution, for: ExGraphQL.Language.Field do

alias ExGraphQL.Execution
alias ExGraphQL.Execution.Resolution
alias ExGraphQL.Type

@spec resolve(ExGraphQL.Language.Field.t,
ExGraphQL.Resolution.t,
ExGraphQL.Execution.t) :: {:ok, map} | {:error, any}
def resolve(%{name: name} = ast_node, %{parent_type: parent_type, target: target} = resolution, %{errors: errors, variables: variables, strategy: :serial} = execution) do
def resolve(%{name: name} = ast_node, %{errors: errors, variables: variables, strategy: :serial, resolution: %{parent_type: parent_type, target: target}} = execution) do
field = Type.field(parent_type, ast_node.name)
if field do
arguments = Execution.LiteralInput.arguments(ast_node.arguments, field.args, variables)
arguments = Execution.Arguments.build(ast_node.arguments, field.args, variables)
case field do
%{resolve: nil} ->
target |> Map.get(name |> String.to_atom) |> result(ast_node, field, resolution, execution)
target |> Map.get(name |> String.to_atom) |> result(ast_node, field, execution)
%{resolve: resolver} ->
resolver.(arguments, execution, resolution)
|> process_raw_result(ast_node, field, resolution, execution)
resolver.(arguments, execution)
|> process_raw_result(ast_node, field, execution)
end
else
error_info = %{name: ast_node.name, role: :field, value: "Not present in schema"}
Expand All @@ -24,11 +24,11 @@ defimpl ExGraphQL.Execution.Resolution, for: ExGraphQL.Language.Field do
end
end

defp process_raw_result({:ok, value}, ast_node, field, resolution, execution) do
defp process_raw_result({:ok, value}, ast_node, field, execution) do
value
|> result(ast_node, field, resolution, execution)
|> result(ast_node, field, execution)
end
defp process_raw_result({:error, error}, ast_node, _field, _resolution, execution) do
defp process_raw_result({:error, error}, ast_node, _field, execution) do
new_errors = error
|> List.wrap
|> Enum.map(fn (value) ->
Expand All @@ -37,7 +37,7 @@ defimpl ExGraphQL.Execution.Resolution, for: ExGraphQL.Language.Field do
end)
{:skip, %{execution | errors: new_errors ++ execution.errors }}
end
defp process_raw_result(_other, ast_node, _field, _resolution, execution) do
defp process_raw_result(_other, ast_node, _field, execution) do
error_info = %{
name: ast_node.name,
role: :field,
Expand All @@ -47,16 +47,13 @@ defimpl ExGraphQL.Execution.Resolution, for: ExGraphQL.Language.Field do
{:skip, %{execution | errors: [error|execution.errors]}}
end

defp result(nil, _ast_node, _field, _resolution, execution) do
defp result(nil, _ast_node, _field, execution) do
{:ok, nil, execution}
end
defp result(value, ast_node, field, _resolution, execution) do
defp result(value, ast_node, field, execution) do
resolved_type = Type.resolve_type(field.type, value)
Execution.Resolution.resolve(
resolved_type,
%Execution.Resolution{type: resolved_type, ast_node: ast_node, target: value},
execution
)
next_resolution = %Resolution{type: resolved_type, ast_node: ast_node, target: value}
Resolution.resolve(resolved_type, %{execution | resolution: next_resolution})
end

end
6 changes: 3 additions & 3 deletions lib/ex_graphql/execution/resolution/list.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ defimpl ExGraphQL.Execution.Resolution, for: ExGraphQL.Type.List do

alias ExGraphQL.Execution.Resolution

def resolve(%{of_type: wrapped_type}, %{ast_node: %{selection_set: selection_set}, target: target}, execution) do
def resolve(%{of_type: wrapped_type}, %{resolution: %{ast_node: %{selection_set: selection_set}, target: target}} = execution) do
%{values: values_to_return, execution: execution_to_return} = target
|> Enum.reduce(%{values: [], execution: execution}, fn (value_to_resolve, %{values: values_before, execution: current_execution}) ->
this_resolution = %Resolution{type: wrapped_type, target: value_to_resolve}
{:ok, result, next_execution} = Resolution.resolve(
selection_set,
%Resolution{type: wrapped_type, target: value_to_resolve},
current_execution
%{current_execution | resolution: this_resolution}
)
%{values: [result|values_before], execution: next_execution}
end)
Expand Down
6 changes: 3 additions & 3 deletions lib/ex_graphql/execution/resolution/object_type.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ defimpl ExGraphQL.Execution.Resolution, for: ExGraphQL.Type.ObjectType do

alias ExGraphQL.Execution.Resolution

def resolve(object_type, %{ast_node: %{selection_set: selection_set}, target: target}, execution) do
def resolve(object_type, %{resolution: %{ast_node: %{selection_set: selection_set}, target: target}} = execution) do
deeper_resolution = %Resolution{type: object_type, target: target}
Resolution.resolve(
selection_set,
%Resolution{type: object_type, target: target},
execution
%{execution | resolution: deeper_resolution}
)
end

Expand Down
6 changes: 3 additions & 3 deletions lib/ex_graphql/execution/resolution/operation_definition.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ defimpl ExGraphQL.Execution.Resolution, for: ExGraphQL.Language.OperationDefinit

alias ExGraphQL.Execution.Resolution

def resolve(operation, resolution, execution) do
def resolve(operation, %{resolution: %{target: target}} = execution) do
deeper_resolution = %Resolution{type: target}
Resolution.resolve(
operation.selection_set,
%Resolution{type: resolution.target},
execution
%{execution | resolution: deeper_resolution}
)
end

Expand Down
2 changes: 1 addition & 1 deletion lib/ex_graphql/execution/resolution/scalar.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
defimpl ExGraphQL.Execution.Resolution, for: ExGraphQL.Type.Scalar do

def resolve(%{parse_value: parse_value}, %{target: target}, execution) do
def resolve(%{parse_value: parse_value}, %{resolution: %{target: target}} = execution) do
{:ok, parse_value.(target), execution}
end

Expand Down
Loading