defmodule Cognac do
@moduledoc """
"""
alias Cognac.Query
alias Cognac.OperationArgument
@doc """
Convert keyword list/tuple list to GraphQL query string
```elixir
iex> query = [hero: [:name, friends: [:name]]]
iex> Cognac.query(query) |> IO.puts
query{hero{name friends{name}}}
```
## Options
* `:output`
* `:iodata` (default) - Outputs as IO data
* `:binary` - Outputs query as a binary string
* `pretty`
* `false` (default) - Outputs minimal query
* `true` - Outputs prettified query with indentation and linebreaks
"""
@spec query(list() | keyword()) :: binary() | iodata()
def query(query, options \\ []) do
["query", Query.build(query, options)]
|> binary_or_iodata(options)
end
@doc """
Convert keyword list/tuple list to GraphQL mutation query string
```elixir
iex> mutation = [hero: [:name, friends: [:name]]]
iex> Cognac.mutation(mutation) |> IO.puts
mutation{updateHero(name:\"Steve\"){name}}
```
## Options
* `:output`
* `:iodata` (default) - Outputs as IO data
* `:binary` - Outputs query as a binary string
* `pretty`
* `false` (default) - Outputs minimal query
* `true` - Outputs prettified query with indentation and linebreaks
"""
@spec mutation(list() | keyword()) :: binary() | iodata()
def mutation(query, options \\ []) do
["mutation", Query.build(query, options)]
|> binary_or_iodata(options)
end
@doc """
Convert keyword list/tuple list to GraphQL subscription query string
```elixir
iex> subscription = [heroUpdated: [:name]]
iex> Cognac.subscription(subscription) |> IO.puts
subscription{heroUpdated{name}}
```
## Options
* `:output`
* `:iodata` (default) - Outputs as IO data
* `:binary` - Outputs query as a binary string
* `pretty`
* `false` (default) - Outputs minimal query
* `true` - Outputs prettified query with indentation and linebreaks
"""
@spec subscription(list() | keyword()) :: binary() | iodata()
def subscription(query, options \\ []) do
["subscription", Query.build(query, options)]
|> binary_or_iodata(options)
end
@spec query_operation(binary(), list() | keyword(), list() | keyword(), keyword()) ::
binary() | iodata()
def query_operation(name, arguments, query, options \\ []) do
arguments = OperationArgument.build(arguments)
["query ", name, arguments, " ", Query.build(query, options)]
end
@spec mutation_operation(binary(), list() | keyword(), list() | keyword(), keyword()) ::
binary() | iodata()
def mutation_operation(name, arguments, query, options \\ []) do
arguments = OperationArgument.build(arguments)
["mutation ", name, arguments, Query.build(query, options)]
end
@spec subscription_operation(binary(), list() | keyword(), list() | keyword(), keyword()) ::
binary() | iodata()
def subscription_operation(name, arguments, query, options \\ []) do
arguments = OperationArgument.build(arguments)
["subscription ", name, arguments, Query.build(query, options)]
end
@doc """
Marks value as variable, helping with correct annotation using ($) and all that jazz.
"""
defmacro variable(name) when is_binary(name) do
quote do: {:variable, unquote(name)}
end
defmacro variable(name) when is_atom(name) do
quote do: {:variable, unquote(name)}
end
@doc """
Marks type as non-null, appending with an exclamation mark (!).
"""
defmacro non_null(type) do
quote do: [to_string(unquote(type)), ?!]
end
defp binary_or_iodata(iodata, options) do
case options[:output] do
:iodata -> iodata
:binary -> IO.iodata_to_binary(iodata)
_ -> iodata
end
end
end