Skip to content

Commit ab04357

Browse files
authored
Add igniter powered oban_web installer (#116)
1 parent 0c26a00 commit ab04357

File tree

3 files changed

+199
-0
lines changed

3 files changed

+199
-0
lines changed

lib/mix/tasks/oban_web.install.ex

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
defmodule Mix.Tasks.ObanWeb.Install.Docs do
2+
@moduledoc false
3+
4+
def short_doc do
5+
"Installs Oban Web into your Phoenix application"
6+
end
7+
8+
def example do
9+
"mix oban_web.install"
10+
end
11+
12+
def long_doc do
13+
"""
14+
#{short_doc()}
15+
16+
This task configures your Phoenix application to use the Oban Web dashboard:
17+
18+
* Adds the required `Oban.Web.Router` import
19+
* Sets up the dashboard route at "/oban" within the :dev_routes conditional
20+
21+
## Example
22+
23+
```bash
24+
#{example()}
25+
"""
26+
end
27+
end
28+
29+
if Code.ensure_loaded?(Igniter) do
30+
defmodule Mix.Tasks.ObanWeb.Install do
31+
@shortdoc "#{__MODULE__.Docs.short_doc()}"
32+
33+
@moduledoc __MODULE__.Docs.long_doc()
34+
use Igniter.Mix.Task
35+
36+
@impl Igniter.Mix.Task
37+
def info(_argv, _composing_task) do
38+
%Igniter.Mix.Task.Info{
39+
group: :oban,
40+
installs: [{:oban, "~> 2.0"}],
41+
example: __MODULE__.Docs.example()
42+
}
43+
end
44+
45+
@impl Igniter.Mix.Task
46+
def igniter(igniter) do
47+
case Igniter.Libs.Phoenix.select_router(igniter) do
48+
{igniter, nil} ->
49+
Igniter.add_warning(igniter, """
50+
No Phoenix router found, Phoenix Liveview is needed for Oban Web
51+
""")
52+
53+
{igniter, router} ->
54+
update_router(igniter, router)
55+
end
56+
end
57+
58+
defp update_router(igniter, router) do
59+
zipper = &do_update_router(igniter, &1)
60+
61+
case Igniter.Project.Module.find_and_update_module(igniter, router, zipper) do
62+
{:ok, igniter} ->
63+
igniter
64+
65+
{:error, igniter} ->
66+
Igniter.add_warning(igniter, """
67+
Something went wrong, please check the Oban Web install docs for manual setup instructions
68+
""")
69+
end
70+
end
71+
72+
defp do_update_router(igniter, zipper) do
73+
web_module = Igniter.Libs.Phoenix.web_module(igniter)
74+
app_name = Igniter.Project.Application.app_name(igniter)
75+
76+
with {:ok, zipper} <- add_import(zipper, web_module) do
77+
add_route(zipper, app_name)
78+
end
79+
end
80+
81+
defp add_import(zipper, web_module) do
82+
with {:ok, zipper} <- Igniter.Code.Module.move_to_use(zipper, web_module) do
83+
{:ok, Igniter.Code.Common.add_code(zipper, "\nimport Oban.Web.Router")}
84+
end
85+
end
86+
87+
defp add_route(zipper, app_name) do
88+
matcher = &dev_routes?(&1, app_name)
89+
90+
with {:ok, zipper} <- Igniter.Code.Function.move_to_function_call(zipper, :if, 2, matcher),
91+
{:ok, zipper} <- Igniter.Code.Common.move_to_do_block(zipper) do
92+
{:ok,
93+
Igniter.Code.Common.add_code(zipper, """
94+
scope "/" do
95+
pipe_through :browser
96+
97+
oban_dashboard "/oban"
98+
end
99+
""")}
100+
end
101+
end
102+
103+
defp dev_routes?(zipper, app_name) do
104+
case Igniter.Code.Function.move_to_nth_argument(zipper, 0) do
105+
{:ok, zipper} ->
106+
Igniter.Code.Function.function_call?(zipper, {Application, :compile_env}, 2) and
107+
Igniter.Code.Function.argument_equals?(zipper, 0, app_name) and
108+
Igniter.Code.Function.argument_equals?(zipper, 1, :dev_routes)
109+
110+
_ ->
111+
false
112+
end
113+
end
114+
end
115+
else
116+
defmodule Mix.Tasks.ObanWeb.Task.Install do
117+
@shortdoc "#{__MODULE__.Docs.short_doc()} | Install `igniter` to use"
118+
119+
@moduledoc __MODULE__.Docs.long_doc()
120+
121+
use Mix.Task
122+
123+
def run(_argv) do
124+
Mix.shell().error("""
125+
The task 'ObanWeb.Task.Install' requires igniter. Please install igniter and try again.
126+
127+
For more information, see: https://hexdocs.pm/igniter/readme.html#installation
128+
""")
129+
130+
exit({:shutdown, 1})
131+
end
132+
end
133+
end

mix.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ defmodule Oban.Web.MixProject do
109109
# Tooling
110110
{:credo, "~> 1.7", only: [:test, :dev], runtime: false},
111111
{:floki, "~> 0.33", only: [:test, :dev]},
112+
{:igniter, "~> 0.5", only: [:dev, :test]},
112113

113114
# Docs and Publishing
114115
{:ex_doc, "~> 0.34", only: :dev, runtime: false},
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
defmodule Mix.Tasks.ObanWeb.InstallTest do
2+
use ExUnit.Case, async: true
3+
4+
import Igniter.Test
5+
6+
test "installation adds the route the neccessary setup to the router" do
7+
test_project()
8+
|> Igniter.Project.Module.create_module(TestWeb.Router, """
9+
use TestWeb, :router
10+
11+
pipeline :browser do
12+
plug :accepts, ["html"]
13+
plug :fetch_session
14+
plug :fetch_live_flash
15+
plug :put_root_layout, {DevWeb.LayoutView, :root}
16+
plug :protect_from_forgery
17+
plug :put_secure_browser_headers
18+
end
19+
20+
pipeline :api do
21+
plug :accepts, ["json"]
22+
end
23+
24+
# Enable LiveDashboard and Swoosh mailbox preview in development
25+
if Application.compile_env(:test, :dev_routes) do
26+
# If you want to use the LiveDashboard in production, you should put
27+
# it behind authentication and allow only admins to access it.
28+
# If your application does not have an admins-only section yet,
29+
# you can use Plug.BasicAuth to set up some basic authentication
30+
# as long as you are also using SSL (which you should anyway).
31+
import Phoenix.LiveDashboard.Router
32+
33+
scope "/dev" do
34+
pipe_through :browser
35+
36+
live_dashboard "/dashboard", metrics: EdenWeb.Telemetry
37+
forward "/mailbox", Plug.Swoosh.MailboxPreview
38+
end
39+
end
40+
""")
41+
|> apply_igniter!()
42+
|> Igniter.compose_task("oban_web.install")
43+
|> assert_has_patch("lib/test_web/router.ex", """
44+
...|
45+
2 2 | use TestWeb, :router
46+
3 3 |
47+
4 + | import Oban.Web.Router
48+
5 + |
49+
4 6 | pipeline :browser do
50+
5 7 | plug(:accepts, ["html"])
51+
...|
52+
30 32 | forward("/mailbox", Plug.Swoosh.MailboxPreview)
53+
31 33 | end
54+
34 + |
55+
35 + | scope "/" do
56+
36 + | pipe_through(:browser)
57+
37 + |
58+
38 + | oban_dashboard("/oban")
59+
39 + | end
60+
32 40 | end
61+
33 41 |end
62+
...|
63+
""")
64+
end
65+
end

0 commit comments

Comments
 (0)