Current section
Files
Jump to
Current section
Files
lib/blunt/absinthe/field.ex
defmodule Blunt.Absinthe.Field do
@moduledoc false
alias Blunt.DispatchContext, as: Context
alias Blunt.Absinthe.{AbsintheErrors, Args, Field, Log, Middleware}
@type message_module :: atom()
@spec name(atom, keyword) :: atom()
def name(module, opts) do
[name | _] =
module
|> Module.split()
|> Enum.reverse()
default_function_name =
name
|> to_string
|> Macro.underscore()
|> String.to_atom()
Keyword.get(opts, :as, default_function_name)
end
@spec generate_body(atom(), atom, message_module, keyword) :: {:__block__, [], [...]}
def generate_body(operation, field_name, message_module, opts) do
opts =
opts
|> Keyword.put(:operation, operation)
|> Keyword.put(:field_name, field_name)
args = args(message_module, opts)
description = description(message_module)
{before_resolve, after_resolve} = middleware(opts)
Blunt.Message.Compilation.log(message_module, "regenerated #{operation} #{field_name}")
quote do
unquote_splicing(args)
description unquote(description)
middleware unquote(before_resolve)
resolve(fn parent, args, resolution ->
Field.dispatch_and_resolve(
unquote(operation),
unquote(message_module),
unquote(opts),
parent,
args,
resolution
)
end)
middleware unquote(after_resolve)
end
end
@type middlware_function :: (resolution(), keyword() -> resolution())
@spec middleware(keyword) :: {middlware_function, middlware_function}
def middleware(opts), do: Middleware.middleware(opts)
@spec args(message_module, keyword) :: list
def args(message_module, opts),
do: Args.from_message_fields(message_module, opts)
def description(message_module),
do: message_module.__doc__(:short)
@type resolution :: Absinthe.Resolution.t()
@spec dispatch_and_resolve(atom, atom, keyword, map, map, any) :: {:error, list} | {:ok, any}
def dispatch_and_resolve(operation, message_module, query_opts, parent, args, _resolution) do
opts = put_dispatch_opts(query_opts, operation, args)
results =
args
|> Args.resolve_message_input({message_module, parent, query_opts})
|> message_module.new()
|> message_module.dispatch(opts)
:ok = Log.dump()
case results do
{:error, %Context{} = context} ->
return_value = {:error, AbsintheErrors.from_dispatch_context(context)}
context
|> Context.put_pipeline(:absinthe_resolve, return_value)
|> Context.Shipper.ship()
return_value
{:ok, %Context{} = context} ->
return_value = {:ok, Context.get_last_pipeline(context)}
context
|> Context.put_pipeline(:absinthe_resolve, return_value)
|> Context.Shipper.ship()
return_value
end
end
def put_dispatch_opts(opts, operation, args) do
opts
|> Keyword.put(:return, :context)
|> Keyword.put(operation, true)
|> Keyword.put(:user_supplied_fields, Map.keys(args))
end
end