Packages
dagger
0.9.6
0.21.7
0.21.6
0.21.5
0.21.4
0.21.3
0.21.2
0.21.1
0.21.0
0.20.8
0.20.7
0.20.6
0.20.5
0.20.4
0.20.3
0.20.2
0.20.1
0.20.0
0.19.11
0.19.10
0.19.9
0.19.8
0.19.7
0.19.6
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.19
0.18.18
0.18.17
0.18.16
0.18.15
0.18.14
0.18.13
0.18.12
0.18.11
0.18.10
0.18.9
0.18.8
0.18.7
0.18.5
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
0.17.2
0.17.1
0.17.0
0.16.3
0.16.2
0.16.1
0.16.0
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.0
0.13.7
0.13.6
0.13.5
0.13.4
0.13.3
0.13.2
0.13.1
0.13.0
0.12.7
0.12.6
0.12.5
0.12.4
0.12.3
0.12.2
0.12.1
0.12.0
0.11.9
0.11.8
0.11.7
0.11.6
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.3
0.10.2
0.10.1
0.10.0
0.9.11
0.9.10
0.9.9
0.9.8
0.9.7
0.9.6
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.8
0.8.7
0.8.6
0.8.5
0.8.4
0.8.2
0.0.0
retired
Dagger SDK for Elixir
Current section
Files
Jump to
Current section
Files
lib/dagger/query_builder.ex
defmodule Dagger.QueryBuilder.Selection do
@moduledoc false
defstruct [:name, :args, :prev, alias: ""]
def query(), do: %__MODULE__{}
def select(%__MODULE__{} = selection, name) when is_binary(name) do
select_with_alias(selection, "", name)
end
def select_with_alias(%__MODULE__{} = selection, alias, name)
when is_binary(alias) and is_binary(name) do
%__MODULE__{
name: name,
alias: alias,
prev: selection
}
end
def arg(%__MODULE__{args: args} = selection, name, value) when is_binary(name) do
args = args || %{}
%{selection | args: Map.put(args, name, value)}
end
def build(%__MODULE__{} = selection) do
fields = build_fields(selection, [])
Enum.join(fields, "{") <> String.duplicate("}", Enum.count(fields) - 1)
end
def build_fields(%__MODULE__{prev: nil}, acc) do
["query" | acc]
end
def build_fields(%__MODULE__{prev: selection, name: name, args: args, alias: alias}, acc) do
q = [build_alias(alias) | [name | build_args(args)]]
build_fields(selection, [IO.iodata_to_binary(q) | acc])
end
defp build_alias(""), do: []
defp build_alias(alias), do: [alias, ~c":"]
defp build_args(nil), do: []
defp build_args(args) do
fun = fn {name, value} -> [name, ~c":", encode_value(value)] end
[~c"(", Enum.map(args, fun) |> Enum.intersperse(","), ~c")"]
end
defp encode_value(value) when is_atom(value) and not is_boolean(value),
do: encode_value(to_string(value))
defp encode_value(value) when is_binary(value) do
string =
value
|> String.replace("\n", "\\n")
|> String.replace("\t", "\\t")
|> String.replace("\"", "\\\"")
[~c"\"", string, ~c"\""]
end
defp encode_value(value) when is_list(value) do
[~c"[", Enum.map(value, &encode_value/1) |> Enum.intersperse(","), ~c"]"]
end
defp encode_value(value) when is_struct(value) do
value
|> Map.from_struct()
|> encode_value()
end
defp encode_value(value) when is_map(value) do
fun = fn {name, value} ->
[to_string(name), ~c":", encode_value(value)]
end
[~c"{", Enum.map(value, fun) |> Enum.intersperse(","), ~c"}"]
end
defp encode_value(value), do: [to_string(value)]
def path(selection) do
path(selection, [])
end
def path(%__MODULE__{prev: nil, name: nil}, acc), do: acc
def path(%__MODULE__{prev: selection, name: name}, acc), do: path(selection, [name | acc])
end
defmodule Dagger.QueryError do
@moduledoc false
defstruct [:errors]
end
defmodule Dagger.QueryBuilder do
@moduledoc false
alias Dagger.QueryBuilder.Selection
alias Dagger.Internal.Client
def execute(selection, client) do
q = Selection.build(selection)
case Client.query(client, q) do
{:ok, %{status: 200, body: %{"data" => nil, "errors" => errors}}} ->
{:error, %Dagger.QueryError{errors: errors}}
{:ok, %{status: 200, body: %{"data" => data}}} ->
{:ok, select_data(data, Selection.path(selection) |> Enum.reverse())}
otherwise ->
otherwise
end
end
defp select_data(data, [sub_selection | path]) do
case sub_selection |> String.split() do
[selection] ->
get_in(data, Enum.reverse([selection | path]))
selections ->
case get_in(data, Enum.reverse(path)) do
data when is_list(data) -> Enum.map(data, &Map.take(&1, selections))
data when is_map(data) -> Map.take(data, selections)
end
end
end
defmacro __using__(_opts) do
quote do
import Dagger.QueryBuilder.Selection
import Dagger.QueryBuilder, only: [execute: 2]
end
end
end