Current section
Files
Jump to
Current section
Files
lib/absinthe_throttle.ex
defmodule AbsintheThrottle do
defmacro __using__(opts) do
adapter = Keyword.fetch!(opts, :adapter)
arguments = Keyword.get(opts, :arguments, nil)
result_phase = Keyword.get(opts, :result_phase, Absinthe.Phase.Document.Execution.Resolution)
quote location: :keep do
use Absinthe.Phase
defmodule Plug do
@parent __MODULE__
|> Atom.to_string()
|> String.split(".")
|> Enum.drop(-1)
|> Enum.join(".")
|> String.to_atom()
def pipeline(config, opts) do
config
|> Absinthe.Plug.default_pipeline(opts)
|> Absinthe.Pipeline.insert_before(Absinthe.Phase.Document.Execution.Resolution, {@parent, result_phase: unquote(result_phase)})
end
end
def run(blueprint, options \\ []) do
arguments = rewrite_args(unquote(arguments), blueprint)
case apply(unquote(adapter), :transaction, arguments) do
{:ok, input} = res -> res
{:error, reason} = error ->
root_value = blueprint.resolution.root_value
info = build_info(blueprint, root_value)
acc = blueprint.resolution.acc
resolution = %{blueprint.resolution |
acc: acc,
validation_errors: [format_error(reason)]}
{:jump, %{blueprint | resolution: resolution}, Keyword.fetch!(options, :result_phase)}
end
end
def pipeline(schema) do
schema
|> Absinthe.Pipeline.for_document()
|> Absinthe.Pipeline.insert_before(Absinthe.Phase.Document.Execution.Resolution, {__MODULE__, result_phase: unquote(result_phase)})
end
defp rewrite_args(nil, blueprint), do: []
defp rewrite_args([], blueprint), do: []
defp rewrite_args(xs, blueprint), do: [blueprint | [xs]]
defp format_error(reason) do
case split_error_value(reason) do
{[], _} -> error("error", [])
{[message: message], extra} -> error(message, extra)
end
end
defp error(message, extra \\ []) do
%Absinthe.Phase.Error{
phase: __MODULE__,
message: to_string(message),
extra: Map.new(extra)
}
end
defp split_error_value(error_value) when is_list(error_value) or is_map(error_value) do
Keyword.split(Enum.to_list(error_value), [:message])
end
defp split_error_value(error_value) do
{[message: error_value], []}
end
defp build_info(bp_root, root_value) do
context = bp_root.resolution.context
%Absinthe.Resolution{
adapter: bp_root.adapter,
context: context,
root_value: root_value,
schema: bp_root.schema,
source: root_value,
fragments: Map.new(bp_root.fragments, &{&1.name, &1}),
}
end
end
end
end