Current section

Files

Jump to
neuron lib neuron.ex
Raw

lib/neuron.ex

defmodule Neuron do
alias Neuron.{Response, Connection, Config, Fragment}
@moduledoc """
Neuron is a GraphQL client for elixir.
## Usage
```elixir
iex> Neuron.Config.set(url: "https://example.com/graph")
iex> Neuron.query(\"""
{
films {
title
}
}
\""")
# Response will be:
{:ok, %Neuron.Response{body: %{"data" => {"films" => [%{"title" => "A New Hope"}]}}%, status_code: 200, headers: []}}
# You can also run mutations
iex> Neuron.query(\"""
mutation createUser($name: String!) {
createUser(name: $name) {
id
name
}
}
\""",
%{name: "uesteibar"}
)
"""
@doc """
runs a query request to your graphql endpoint.
## Example
```elixir
Neuron.query(\"""
{
films {
count
}
}
\""")
```
You can pass variables for your query
## Example
```elixir
Neuron.query(
\"""
mutation createUser($name: String!) {
createUser(name: $name) {
id
name
}
}
\""",
%{name: "uesteibar"}
)
```
You can also overwrite parameters set on `Neuron.Config` by passing them as options.
## Example
```elixir
Neuron.query(
\"""
mutation createUser($name: String!) {
createUser(name: $name) {
id
name
}
}
\""",
%{name: "uesteibar"},
url: "https://www.other.com/graphql"
)
```
"""
@spec query(query_string :: String.t(), variables :: map(), options :: keyword()) ::
{:ok, Neuron.Response.t()}
| {:error, Neuron.Response.t() | Neuron.JSONParseError.t() | HTTPoison.Error.t()}
def query(query_string, variables \\ %{}, options \\ []) do
json_library = json_library(options)
query_string
|> Fragment.insert_into_query()
|> build_body()
|> insert_variables(variables)
|> json_library.encode!()
|> run(options)
end
@doc """
Returns the JSON library that is configured in Neuron. Default is Jason.
"""
@spec json_library :: module()
def json_library() do
Config.get(:json_library) || Jason
end
defp json_library(options) do
Keyword.get(options, :json_library, json_library())
end
defp run(body, options) do
body
|> run_query(options)
|> handle_response(options)
end
defp run_query(body, options) do
url = url(options)
headers = build_headers(options)
connection_opts = connection_options(options)
Connection.post(url, body, %{headers: headers, connection_opts: connection_opts})
end
defp build_body(query_string), do: %{query: query_string}
defp insert_variables(body, variables) do
Map.put(body, :variables, variables)
end
defp handle_response(response, options) do
json_library = json_library(options)
parsed_options = parse_options(options)
Response.handle(response, json_library, parsed_options)
end
defp url(options) do
Keyword.get(options, :url) || Config.get(:url)
end
defp build_headers(options) do
Keyword.merge(["Content-Type": "application/json"], headers(options))
end
defp headers(options) do
Keyword.get(options, :headers, Config.get(:headers) || [])
end
defp parse_options(options) do
Keyword.get(options, :parse_options, Config.get(:parse_options) || [])
end
defp connection_options(options) do
Keyword.get(options, :connection_opts, Config.get(:connection_opts) || [])
end
end