Packages
dagger
0.21.2
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/mod/registry.ex
defmodule Dagger.Mod.Registry do
@moduledoc false
defstruct modules: %{}, enums: []
def register(root_module) do
root_module
|> traverse()
|> Enum.reduce(%__MODULE__{}, &put_module(&2, &1))
end
def put_module(%__MODULE__{} = registry, module) when is_atom(module) do
if function_exported?(module, :__kind__, 0) do
case module.__kind__() do
:enum ->
%__MODULE__{registry | enums: [module | registry.enums]}
:object ->
%__MODULE__{registry | modules: Map.put(registry.modules, module.__name__(), module)}
_ ->
registry
end
else
registry
end
end
def all_modules(%__MODULE__{} = registry) do
(Map.values(registry.modules) ++ registry.enums) |> Enum.sort()
end
def get_module_by_name!(%__MODULE__{} = registry, name) when is_binary(name) do
case registry.modules[name] do
nil -> raise "Cannot find `#{name}` in the registry."
module -> module
end
end
defp traverse(root_module) do
root_module.__object__(:functions)
|> traverse([root_module])
end
defp traverse([], modules), do: modules |> List.flatten() |> Enum.uniq() |> Enum.reverse()
defp traverse([{_, fun_def} | funs], modules) do
enum_modules = collect_enums_from_funs(fun_def)
ret_module = fun_def.return
additional_modules =
if object?(ret_module) and ret_module not in modules do
traverse(ret_module)
else
[]
end
modules_to_add = enum_modules ++ additional_modules
traverse(funs, [modules_to_add | modules])
end
defp collect_enums_from_funs(fun_def) do
fun_def.args
|> Enum.flat_map(fn {_name, arg_def} ->
type = Keyword.fetch!(arg_def, :type)
collect_enums_from_args(type)
end)
end
defp collect_enums_from_args({:optional, type}), do: collect_enums_from_args(type)
defp collect_enums_from_args({:list, type}), do: collect_enums_from_args(type)
defp collect_enums_from_args(module) when is_atom(module) do
if Code.ensure_loaded?(module) and function_exported?(module, :__kind__, 0) and
module.__kind__() == :enum do
[module]
else
[]
end
end
defp collect_enums_from_args(_), do: []
defp object?(:integer), do: false
defp object?(:float), do: false
defp object?(:boolean), do: false
defp object?(:string), do: false
defp object?({:list, type}), do: object?(type)
defp object?({:optional, type}), do: object?(type)
defp object?(type),
do: type.__kind__() == :object and function_exported?(type, :__object__, 1)
end