defmodule Absinthe do
@moduledoc """
Documentation for the Absinthe package, a toolkit for building GraphQL
APIs with Elixir.
For usage information, see [the documentation](https://hexdocs.pm/absinthe), which
includes guides, API information for important modules, and links to useful resources.
"""
defmodule SerializationError do
@moduledoc """
An error during serialization.
"""
defexception message: "serialization failed"
end
defmodule ExecutionError do
@moduledoc """
An error during execution.
"""
defexception message: "execution failed"
end
defmodule AnalysisError do
@moduledoc """
An error during analysis.
"""
defexception message: "analysis failed"
end
@type result_selection_t :: %{
String.t() =>
nil
| integer
| float
| boolean
| binary
| atom
| result_selection_t
| [result_selection_t]
}
@type result_error_t ::
%{message: String.t()}
| %{message: String.t(), locations: [%{line: pos_integer, column: integer}]}
@type result_t ::
%{data: nil | result_selection_t}
| %{data: nil | result_selection_t, errors: [result_error_t]}
| %{errors: [result_error_t]}
@type pipeline_modifier_fun :: (Absinthe.Pipeline.t(), Keyword.t() -> Absinthe.Pipeline.t())
@doc """
Evaluates a query document against a schema, with options.
## Options
* `:adapter` - The name of the adapter to use. See the `Absinthe.Adapter`
behaviour and the `Absinthe.Adapter.Passthrough` and
`Absinthe.Adapter.LanguageConventions` modules that implement it.
(`Absinthe.Adapter.LanguageConventions` is the default value for this option.)
* `:operation_name` - If more than one operation is present in the provided
query document, this must be provided to select which operation to execute.
* `:variables` - A map of provided variable values to be used when filling in
arguments in the provided query document.
* `:context` -> A map of the execution context.
* `:root_value` -> A root value to use as the source for toplevel fields.
* `:analyze_complexity` -> Whether to analyze the complexity before
executing an operation.
* `:max_complexity` -> An integer (or `:infinity`) for the maximum allowed
complexity for the operation being executed.
## Examples
```
\"""
query GetItemById($id: ID) {
item(id: $id) {
name
}
}
\"""
|> Absinthe.run(App.Schema, variables: %{"id" => params[:item_id]})
```
See the `Absinthe` module documentation for more examples.
"""
@type run_opts :: [
context: %{},
adapter: Absinthe.Adapter.t(),
root_value: term,
operation_name: String.t(),
analyze_complexity: boolean,
variables: %{optional(String.t()) => any()},
max_complexity: non_neg_integer | :infinity,
pipeline_modifier: pipeline_modifier_fun()
]
@type run_result :: {:ok, result_t} | {:error, String.t()}
@spec run(
binary | Absinthe.Language.Source.t() | Absinthe.Language.Document.t(),
Absinthe.Schema.t(),
run_opts
) :: run_result
def run(document, schema, options \\ []) do
pipeline_modifier = options[:pipeline_modifier] || (&pipeline_identity/2)
pipeline =
schema
|> Absinthe.Pipeline.for_document(options)
|> pipeline_modifier.(options)
case Absinthe.Pipeline.run(document, pipeline) do
{:ok, %{result: result}, _phases} ->
{:ok, result}
{:error, msg, _phases} ->
{:error, msg}
end
end
@doc """
Evaluates a query document against a schema, without options.
## Options
See `run/3` for the available options.
"""
@spec run!(
binary | Absinthe.Language.Source.t() | Absinthe.Language.Document.t(),
Absinthe.Schema.t(),
run_opts
) :: result_t | no_return
def run!(input, schema, options \\ []) do
case run(input, schema, options) do
{:ok, result} -> result
{:error, err} -> raise ExecutionError, message: err
end
end
defp pipeline_identity(pipeline, _options), do: pipeline
end