ash/lib/mix/tasks/ash.generate_resource_diagrams.ex
Zach Daniel 46ed97dd10 improvement: add ash.rollback mix task
chore: fix some naming/mix task steps
2024-04-09 20:24:08 -04:00

88 lines
2.4 KiB
Elixir

defmodule Mix.Tasks.Ash.GenerateResourceDiagrams do
@moduledoc """
Generates a Mermaid Resource Diagram for each Ash domain.
## Prerequisites
This mix task requires the Mermaid CLI to be installed on your system.
See https://github.com/mermaid-js/mermaid-cli
## Command line options
* `--type` - `er` or `class` (defaults to `class`)
* `--only` - only generates for the given domain
* `--format` - Can be set to one of either:
* `plain` - Prints just the mermaid output as text. This is the default.
* `md` - Prints the mermaid diagram in a markdown code block.
* `svg` - Generates an SVG
* `pdf` - Generates a PDF
* `png` - Generates a PNG
"""
use Mix.Task
@recursive true
@shortdoc "Generates Mermaid Resource Diagrams for each Ash domain"
@doc @shortdoc
def run(argv) do
Mix.Task.run("compile")
{opts, _} =
OptionParser.parse!(argv,
strict: [only: :keep, type: :string, format: :string],
aliases: [o: :only, t: :type, f: :format]
)
only =
if opts[:only] && opts[:only] != [] do
Enum.map(List.wrap(opts[:only]), &Path.expand/1)
end
format = Keyword.get(opts, :format, "plain")
domains()
|> Task.async_stream(
fn domain ->
source = domain.module_info(:compile)[:source]
if is_nil(only) || Path.expand(source) in only do
case Keyword.get(opts, :type, "class") do
"er" ->
Mix.Mermaid.generate_diagram(
source,
"mermaid-er-diagram",
format,
Ash.Domain.Info.Diagram.mermaid_er_diagram(domain),
"Generated ER Diagram for #{inspect(domain)}"
)
"class" ->
Mix.Mermaid.generate_diagram(
source,
"mermaid-class-diagram",
format,
Ash.Domain.Info.Diagram.mermaid_class_diagram(domain),
"Generated Class Diagram for #{inspect(domain)}"
)
type ->
Mix.shell().error("""
Invalid resource diagram type `#{type}`.
Valid options are `er` or `class`.
""")
end
end
end,
timeout: :infinity
)
|> Stream.run()
end
defp domains do
Mix.Project.config()[:app]
|> Application.get_env(:ash_domains, [])
end
end