ash_state_machine/lib/charts.ex
2023-04-22 16:50:23 -06:00

47 lines
1.3 KiB
Elixir

defmodule AshStateMachine.Charts do
@moduledoc """
Returns a mermaid flow chart of a given state machine resource.
"""
@spec mermaid_flowchart(Ash.Resource.t()) :: String.t()
def mermaid_flowchart(resource) do
resource
|> AshStateMachine.Info.state_machine_initial_states!()
|> Enum.reduce({["flowchart TD"], MapSet.new()}, fn state, {lines, checked} ->
add_to_chart(resource, state, lines ++ [], checked)
end)
|> elem(0)
|> Enum.join("\n")
end
defp add_to_chart(resource, state, lines, checked) do
if state in checked do
{lines, checked}
else
checked = MapSet.put(checked, state)
state
|> transitions_from(resource)
|> Enum.reduce({lines, checked}, fn event, {lines, checked} ->
Enum.reduce(List.wrap(event.to), {lines, checked}, fn to, {lines, checked} ->
name =
case event.action do
:* -> ""
action -> "|#{action}|"
end
lines = lines ++ ["#{state} --> #{name} #{to}"]
add_to_chart(resource, to, lines, checked)
end)
end)
end
end
defp transitions_from(state, resource) do
resource
|> AshStateMachine.Info.state_machine_transitions()
|> Enum.filter(fn event ->
state in List.wrap(event.from)
end)
end
end