Skip to content

Commit

Permalink
improvement: Migrate phoenix gen to igniter (#261)
Browse files Browse the repository at this point in the history
  • Loading branch information
srikanthkyatham authored Nov 27, 2024
1 parent c89c97d commit 63fa4c7
Show file tree
Hide file tree
Showing 5 changed files with 403 additions and 66 deletions.
5 changes: 3 additions & 2 deletions .formatter.exs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Used by "mix format"
[
import_deps: [:ash],
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
import_deps: [:ash, :phoenix],
plugins: [Phoenix.LiveView.HTMLFormatter],
inputs: ["{mix}.exs", "{config,lib,test}/**/*.{ex,exs,heex}"]
]
97 changes: 48 additions & 49 deletions lib/ash_phoenix/gen/live.ex
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
defmodule AshPhoenix.Gen.Live do
@moduledoc false

def generate_from_cli(argv) do
{domain, resource, opts, _rest} = AshPhoenix.Gen.parse_opts(argv)
def generate_from_cli(%Igniter{} = igniter, options) do
domain = Keyword.fetch!(options, :domain) |> String.to_existing_atom()
resource = Keyword.fetch!(options, :resource) |> String.to_existing_atom()
resource_plural = Keyword.fetch!(options, :resourceplural)
opts = []

generate(
igniter,
domain,
resource,
Keyword.put(opts, :interactive?, true)
Keyword.put(opts, :interactive?, true) |> Keyword.put(:resource_plural, resource_plural)
)
end

def generate(domain, resource, opts \\ []) do
def generate(igniter, domain, resource, opts \\ []) do
Code.ensure_compiled!(domain)
Code.ensure_compiled!(resource)

Expand Down Expand Up @@ -55,13 +59,13 @@ defmodule AshPhoenix.Gen.Live do
[
domain: inspect(domain),
resource: inspect(resource),
web_module: inspect(web_module()),
web_module: inspect(web_module(igniter)),
actor: opts[:actor],
actor_opt: actor_opt(opts)
]
|> add_resource_assigns(resource, opts)

web_live = Path.join([web_path(), "live", "#{assigns[:resource_singular]}_live"])
web_live = Path.join([web_path(igniter), "live", "#{assigns[:resource_singular]}_live"])

generate_opts =
if opts[:interactive?] do
Expand All @@ -70,40 +74,50 @@ defmodule AshPhoenix.Gen.Live do
[force: true, quiet: true]
end

write_formatted_template(
"ash_phoenix.gen.live/index.ex.eex",
"index.ex",
web_live,
assigns,
generate_opts
)

if assigns[:update_action] || assigns[:create_action] do
igniter =
write_formatted_template(
"ash_phoenix.gen.live/form_component.ex.eex",
"form_component.ex",
igniter,
"ash_phoenix.gen.live/index.ex.eex",
"index.ex",
web_live,
assigns,
generate_opts
)
end

write_formatted_template(
"ash_phoenix.gen.live/show.ex.eex",
"show.ex",
web_live,
assigns,
generate_opts
)
igniter =
if assigns[:update_action] || assigns[:create_action] do
write_formatted_template(
igniter,
"ash_phoenix.gen.live/form_component.ex.eex",
"form_component.ex",
web_live,
assigns,
generate_opts
)
else
igniter
end

igniter =
write_formatted_template(
igniter,
"ash_phoenix.gen.live/show.ex.eex",
"show.ex",
web_live,
assigns,
generate_opts
)

if opts[:interactive?] do
Mix.shell().info("""
Add the live routes to your browser scope in #{web_path()}/router.ex:
Add the live routes to your browser scope in #{web_path(igniter)}/router.ex:
#{for line <- live_route_instructions(assigns), do: " #{line}"}
""")
end

igniter
end

defp live_route_instructions(assigns) do
Expand All @@ -123,7 +137,7 @@ defmodule AshPhoenix.Gen.Live do
|> Enum.reject(&is_nil/1)
end

defp write_formatted_template(path, destination, web_live, assigns, generate_opts) do
defp write_formatted_template(igniter, path, destination, web_live, assigns, generate_opts) do
destination_path =
web_live
|> Path.join(destination)
Expand All @@ -137,7 +151,7 @@ defmodule AshPhoenix.Gen.Live do
|> EEx.eval_file(assigns: assigns)
|> formatter_function.()

Mix.Generator.create_file(destination_path, contents, generate_opts)
Igniter.create_new_file(igniter, destination_path, contents, generate_opts)
end

defp add_resource_assigns(assigns, resource, opts) do
Expand Down Expand Up @@ -305,30 +319,15 @@ defmodule AshPhoenix.Gen.Live do
end
end

defp web_path do
web_module().module_info[:compile][:source]
|> Path.relative_to(root_path())
|> Path.rootname()
end
defp web_path(igniter) do
web_module_path = Igniter.Project.Module.proper_location(igniter, web_module(igniter))
lib_dir = Path.dirname(web_module_path)

defp root_path do
Mix.Project.get().module_info[:compile][:source]
|> Path.dirname()
Path.join([lib_dir, Path.basename(web_module_path, ".ex")])
end

defp web_module do
base = Mix.Phoenix.base()

cond do
Mix.Phoenix.context_app() != Mix.Phoenix.otp_app() ->
Module.concat([base])

String.ends_with?(base, "Web") ->
Module.concat([base])

true ->
Module.concat(["#{base}Web"])
end
defp web_module(igniter) do
Igniter.Libs.Phoenix.web_module(igniter)
end

defp template(path) do
Expand Down
54 changes: 40 additions & 14 deletions lib/mix/tasks/ash_phoenix.gen.live.ex
Original file line number Diff line number Diff line change
@@ -1,29 +1,55 @@
defmodule Mix.Tasks.AshPhoenix.Gen.Live do
use Igniter.Mix.Task

@example "mix ash_phoenix.gen.live --domain ExistingDomainName --resource ExistingResourceName --resource-plural ExistingResourceNames"

@shortdoc "Generates liveviews for a given domain and resource."

# --domain
# --resource
# --resource-plural
@moduledoc """
#{@shortdoc}
Generates liveviews for a given domain and resource.
The domain and resource must already exist, this task does not define them.
#{AshPhoenix.Gen.docs()}
For example:
## Example
```bash
mix ash_phoenix.gen.live ExistingDomainName ExistingResourceName
#{@example}
```
## Options
* `--domain` - Existing domain
* `--resource` - Existing resource
* `--resourceplural` - Plural resource name
"""
use Mix.Task

@shortdoc "Generates liveviews for a resource"
def run(argv) do
Mix.Task.run("compile")
def info(_argv, _composing_task) do
%Igniter.Mix.Task.Info{
# Groups allow for overlapping arguments for tasks by the same author
# See the generators guide for more.
group: :ash_phoenix,
example: @example,
schema: [domain: :string, resource: :string, resourceplural: :string],
# Default values for the options in the `schema`.
defaults: [],
# CLI aliases
aliases: [],
# A list of options in the schema that are required
required: [:domain, :resource, :resourceplural]
}
end

if Mix.Project.umbrella?() do
Mix.raise(
"mix phx.gen.live must be invoked from within your *_web application root directory"
)
end
def igniter(igniter, argv) do
# extract options according to `schema` and `aliases` above
options = options!(argv)

AshPhoenix.Gen.Live.generate_from_cli(argv)
# Do your work here and return an updated igniter
igniter
|> AshPhoenix.Gen.Live.generate_from_cli(options)
end
end
4 changes: 3 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,9 @@ defmodule AshPhoenix.MixProject do
{:dialyxir, ">= 0.0.0", only: [:dev, :test], runtime: false},
{:sobelow, ">= 0.0.0", only: [:dev, :test], runtime: false},
{:mix_audit, ">= 0.0.0", only: [:dev, :test], runtime: false},
{:mix_test_watch, "~> 1.0", only: [:dev, :test]}
{:mix_test_watch, "~> 1.0", only: [:dev, :test]},
# Code Generators
{:igniter, "~> 0.4 and >= 0.4.3"}
]
end

Expand Down
Loading

0 comments on commit 63fa4c7

Please sign in to comment.