Packages

The SalesRabbit Service Generator is a package for generating new service applications inside the SalesRabbit ecosystem.

Current section

Files

Jump to
sr_service priv template.build_sdk.ex
Raw

priv/template.build_sdk.ex

defmodule Mix.Tasks.BuildSdk do
@moduledoc false
use Mix.Task
def run(_) do
build_sdk()
end
def build_sdk() do
{_, _, :elixir, _, %{"en" => _module_doc}, _, docs} = module() |> Code.fetch_docs()
fxns =
docs
|> Enum.map(fn
{{:function, name_as_atom, arity}, _, [_signature], :none, %{}} ->
raise("missing docs for #{name_as_atom}/#{arity} inside #{to_string(module())}")
{{:function, name_as_atom, arity}, _, [signature], %{"en" => fxn_doc}, %{}} ->
spacer = if arity == 0, do: "", else: ", "
new_signature = signature |> String.replace_trailing(")", "#{spacer}method \\\\ :call)")
spec = get_spec(name_as_atom, arity)
args =
new_signature
|> String.split("(")
|> List.last()
|> String.split(" \\")
|> List.first()
"""
\t@doc \"\"\"
\t#{fxn_doc}\t\"\"\"
\t#{spec}
\tdef #{new_signature} when method in [:call, :cast], do: go(method, :#{name_as_atom}, [#{args}])
"""
_ ->
""
end)
|> Enum.join("")
file_name = ("sdk/" <> to_string(module(:simple)) <> ".ex") |> String.downcase()
File.write!(
file_name,
"""
defmodule InternalServices.#{module(:simple)} do
# [This module has been automatically generated and should not be modified.]
@moduledoc \"\"\"
SDK for #{module(:simple)}.
\"\"\"
@prefix \"#{to_string(app_name())}\"
@module #{module(:simple)}
#{fxns}
defp go(method, fxn, args), do: InternalServices.Caller.go(method, @prefix, @module, fxn, args)
end
"""
|> Code.format_string!()
)
end
defp get_spec(name, arity) do
with {:ok, module_specs} <- Code.Typespec.fetch_specs(module()),
{_, function_specs} <- List.keyfind(module_specs, {name, arity}, 0) do
Enum.map(function_specs, fn spec ->
spacer = if arity == 0, do: "", else: ", "
spec_string =
name
|> Code.Typespec.spec_to_quoted(spec)
|> Macro.to_string()
|> String.replace(") ::", "#{spacer}:call | :cast) ::")
"@#{:spec} #{spec_string}"
end)
else
_ ->
raise("missing specs for #{name}/#{arity} inside #{to_string(module())}")
end
end
defp module(:simple) do
module()
|> Module.split()
|> List.last()
end
defp module() do
app_name()
|> to_string()
|> String.capitalize()
|> String.to_atom()
|> List.wrap()
|> Module.safe_concat()
end
defp app_name(), do: __MODULE__ |> Application.get_application()
end