improvement: make state diagrams the default chart

docs: docs improvements
This commit is contained in:
Zach Daniel 2023-04-23 00:58:34 -06:00
parent f86b2f6692
commit bd66b9236f
4 changed files with 54 additions and 19 deletions

View file

@ -107,13 +107,13 @@ end
run `mix ash_state_machine.generate_flow_charts` to generate flow charts for your resources. See the task documentation for more. Here is a chart generated from the example above:
```mermaid
flowchart TD
pending --> |confirm| confirmed
confirmed --> |begin_delivery| on_its_way
on_its_way --> |package_arrived| arrived
on_its_way --> |error| error
confirmed --> |error| error
pending --> |error| error
stateDiagram-v2
pending --> confirmed: confirm
confirmed --> on_its_way: begin_delivery
on_its_way --> arrived: package_arrived
on_its_way --> error: error
confirmed --> error: error
pending --> error: error
```
## Learning more

View file

@ -3,18 +3,29 @@ defmodule AshStateMachine.Charts do
Returns a mermaid flow chart of a given state machine resource.
"""
@spec mermaid_state_diagram(Ash.Resource.t()) :: String.t()
def mermaid_state_diagram(resource) do
resource
|> AshStateMachine.Info.state_machine_initial_states!()
|> Enum.reduce({["stateDiagram-v2"], MapSet.new()}, fn state, {lines, checked} ->
add_to_chart(resource, state, lines ++ [], checked, :state_diagram)
end)
|> elem(0)
|> Enum.join("\n")
end
@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)
add_to_chart(resource, state, lines ++ [], checked, :flow_chart)
end)
|> elem(0)
|> Enum.join("\n")
end
defp add_to_chart(resource, state, lines, checked) do
defp add_to_chart(resource, state, lines, checked, type) do
if state in checked do
{lines, checked}
else
@ -24,14 +35,28 @@ defmodule AshStateMachine.Charts do
|> 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}|"
lines =
case type do
:flow_chart ->
name =
case event.action do
:* -> ""
action -> "|#{action}|"
end
lines ++ ["#{state} --> #{name} #{to}"]
:state_diagram ->
name =
case event.action do
:* -> ""
action -> ": #{action}"
end
lines ++ ["#{state} --> #{to}#{name}"]
end
lines = lines ++ ["#{state} --> #{name} #{to}"]
add_to_chart(resource, to, lines, checked)
add_to_chart(resource, to, lines, checked, type)
end)
end)
end

View file

@ -11,6 +11,7 @@ defmodule Mix.Tasks.AshStateMachine.GenerateFlowCharts do
## Command line options
* `--type` - generates a given type. Valid values are `"state_diagram"` and `"flow_chart"`. Defaults to `"state_diagram"`.
* `--only` - only generates the given Flow file
* `--format` - Can be set to one of either:
* `plain` - Prints just the mermaid output as text. This is the default.
@ -30,8 +31,8 @@ defmodule Mix.Tasks.AshStateMachine.GenerateFlowCharts do
{opts, _} =
OptionParser.parse!(argv,
strict: [only: :keep, format: :string],
aliases: [o: :only, f: :format]
strict: [only: :keep, format: :string, type: :string],
aliases: [o: :only, f: :format, t: :type]
)
only =
@ -47,11 +48,20 @@ defmodule Mix.Tasks.AshStateMachine.GenerateFlowCharts do
source = state_machine.module_info(:compile)[:source]
if is_nil(only) || Path.expand(source) in only do
diagram =
case opts[:type] || "state_diagram" do
"state_diagram" ->
AshStateMachine.Charts.mermaid_state_diagram(state_machine)
"flow_chart" ->
AshStateMachine.Charts.mermaid_flowchart(state_machine)
end
Mix.Mermaid.generate_diagram(
source,
"mermaid-flowchart",
format,
AshStateMachine.Charts.mermaid_flowchart(state_machine),
diagram,
"Generated Mermaid flowchart for #{inspect(state_machine)}"
)
end

View file

@ -154,7 +154,7 @@ defmodule AshStateMachineTest do
describe "charts" do
test "it generates the appropriate chart" do
AshStateMachine.Charts.mermaid_flowchart(Order) |> IO.puts()
AshStateMachine.Charts.mermaid_state_diagram(Order) |> IO.puts()
assert AshStateMachine.Charts.mermaid_flowchart(ThreeStates) ==
"""