Current section
Files
Jump to
Current section
Files
lib/dagger/codegen/elixir/templates/object_tmpl.ex
defmodule Dagger.Codegen.Elixir.Templates.ObjectTmpl do
@moduledoc false
alias Dagger.Codegen.Elixir.Function
def render_object(%{"name" => name, "fields" => fields, "description" => desc} = _full_type) do
mod_name = Module.concat([Dagger, Function.format_module_name(name)])
defs = render_functions(Function.format_var_name(name), fields)
quote do
defmodule unquote(mod_name) do
@moduledoc unquote(desc)
use Dagger.QueryBuilder
defstruct [:selection, :client]
unquote_splicing(defs)
end
end
end
def render_functions(mod_var_name, fields) do
for field <- fields do
render_function(mod_var_name, field)
end
end
def render_function(
mod_var_name,
%{
"name" => name,
"args" => args,
"type" => %{"ofType" => type_ref}
} = field
) do
mod_var_name = to_macro_var(mod_var_name)
fun_args = [module_fun_arg(mod_var_name) | fun_args(args)]
fun_body = format_function_body(name, {mod_var_name, args}, type_ref)
Function.define(name, fun_args, nil, fun_body,
doc: format_doc(field),
deprecated: deprecated_reason(field)
)
end
def format_function_body(
field_name,
{mod_var_name, args},
%{"kind" => "OBJECT", "name" => name}
) do
mod_name = Module.concat([Dagger, Function.format_module_name(name)])
args = render_args(args)
quote do
selection = select(unquote(mod_var_name).selection, unquote(field_name))
unquote_splicing(args)
%unquote(mod_name){
selection: selection,
client: unquote(mod_var_name).client
}
end
end
def format_function_body(field_name, {mod_var_name, args}, _) do
args = render_args(args)
quote do
selection = select(unquote(mod_var_name).selection, unquote(field_name))
unquote_splicing(args)
execute(selection, unquote(mod_var_name).client)
end
end
defp deprecated_reason(%{"isDeprecated" => true, "deprecationReason" => reason}) do
String.trim_trailing(reason, ".")
end
defp deprecated_reason(_), do: nil
defp format_doc(%{"description" => desc, "args" => args}) do
sep = ['\n', '\n']
doc = [desc]
required_args_doc =
case format_required_args_doc(args) do
[] -> []
args_doc -> ["## Required Arguments", '\n', '\n', args_doc]
end
optional_args_doc =
case format_optional_args_doc(args) do
[] -> []
args_doc -> ["## Optional Arguments", '\n', '\n', args_doc]
end
(doc ++ sep ++ required_args_doc ++ sep ++ optional_args_doc)
|> IO.iodata_to_binary()
|> String.trim()
end
defp format_required_args_doc(args) do
args
|> Enum.filter(&required_arg?/1)
|> Enum.map(&format_arg_doc/1)
|> Enum.intersperse('\n')
end
defp format_optional_args_doc(args) do
args
|> Enum.filter(&(not required_arg?(&1)))
|> Enum.map(&format_arg_doc/1)
|> Enum.intersperse('\n')
end
defp required_arg?(arg) do
arg["type"]["kind"] == "NON_NULL"
end
defp format_arg_doc(%{"name" => name, "description" => description}) do
name = Function.format_var_name(name)
"* `#{name}` - #{description}"
end
defp render_args(args) do
required_args = render_required_args(args)
optional_args = render_optional_args(args)
required_args ++ optional_args
end
defp render_required_args(args) do
for arg <- args,
arg["type"]["kind"] == "NON_NULL" do
name = Function.format_var_name(fun_arg_name(arg))
quote do
selection = arg(selection, unquote(arg["name"]), unquote(to_macro_var(name)))
end
end
end
defp render_optional_args(args) do
for arg <- args, not required_arg?(arg) do
name = arg["name"]
arg_name = Function.format_var_name(name)
quote do
selection =
if not is_nil(optional_args[unquote(arg_name)]) do
arg(selection, unquote(name), optional_args[unquote(arg_name)])
else
selection
end
end
end
end
defp module_fun_arg(mod_var_name) do
quote do
%__MODULE__{} = unquote(mod_var_name)
end
end
defp fun_args([]), do: []
defp fun_args(args) do
{required_args, optional_args} =
args
|> Enum.split_with(&required_arg?/1)
required_fun_args(required_args) ++ optional_fun_args(optional_args)
end
defp required_fun_args(args) do
args
|> Enum.map(&Function.format_var_name(fun_arg_name(&1)))
|> Enum.map(&to_macro_var/1)
end
defp optional_fun_args([]), do: []
defp optional_fun_args(_args) do
[
quote do
unquote(to_macro_var(:optional_args)) \\ []
end
]
end
defp fun_arg_name(%{"name" => name}) do
name
end
defp to_macro_var(var), do: Macro.var(var, __MODULE__)
end