Current section

Files

Jump to
star_view lib mix tasks star_view.setup.search_controller.ex
Raw

lib/mix/tasks/star_view.setup.search_controller.ex

defmodule Mix.Tasks.StarView.Setup.SearchController.Docs do
@moduledoc false
def short_doc(), do: "Generates an example StarView demo controller with Datastar"
def example(), do: "mix star_view.setup.search_controller"
def long_doc(), do: "#{short_doc()}"
end
if Code.ensure_loaded?(Igniter) do
defmodule Mix.Tasks.StarView.Setup.SearchController do
@shortdoc "#{__MODULE__.Docs.short_doc()}"
@moduledoc __MODULE__.Docs.long_doc()
use Igniter.Mix.Task
@impl Igniter.Mix.Task
def info(_argv, _composing_task) do
%Igniter.Mix.Task.Info{
group: :star_view,
adds_deps: [],
installs: [],
example: __MODULE__.Docs.example(),
only: nil,
positional: [],
composes: [],
schema: [router: :string],
defaults: [],
aliases: [],
required: []
}
end
@impl Igniter.Mix.Task
def igniter(igniter) do
web_module = Igniter.Libs.Phoenix.web_module(igniter)
endpoint_module = Module.concat(web_module, Endpoint)
{phoenix?, igniter} = Igniter.Project.Module.module_exists(igniter, endpoint_module)
igniter
|> maybe_generate_example(web_module, phoenix?)
|> maybe_patch_router(web_module, phoenix?)
end
defp maybe_generate_example(igniter, web_module, false) do
module = Module.concat([web_module, StarViewDemo])
Igniter.Project.Module.create_module(
igniter,
module,
"""
@moduledoc "Example Datastar handler using StarView with Plug."
def handle_event(conn, "increment", signals) do
count = Map.get(signals, "count", 0) + 1
StarView.patch_signals(conn, %{count: count})
end
"""
)
end
defp maybe_generate_example(igniter, web_module, true) do
controller = Module.concat([web_module, SearchController])
template =
Path.join(:code.priv_dir(:star_view), "templates/search_controller.ex.eex")
|> EEx.eval_file(web_module: web_module, controller: controller)
Igniter.Project.Module.create_module(igniter, controller, template)
end
defp maybe_patch_router(igniter, _web_module, false), do: igniter
defp maybe_patch_router(igniter, web_module, true) do
{igniter, router} =
Igniter.Libs.Phoenix.select_router(
igniter,
"Which Phoenix router should StarView add routes to?"
)
if router do
do_patch_router(igniter, web_module, router)
else
Igniter.add_warning(igniter, "No Phoenix router found. Skipping route setup.")
end
end
defp do_patch_router(igniter, web_module, router) do
{_, source, _zipper} = Igniter.Project.Module.find_module!(igniter, router)
source_str = Rewrite.Source.get(source, :content)
already_has_ds_route? = String.contains?(source_str, ~s("/ds/:module/:event"))
igniter =
if already_has_ds_route? do
already_has_demo? = String.contains?(source_str, "/search")
if already_has_demo? do
igniter
else
Igniter.Libs.Phoenix.append_to_scope(
igniter,
"/",
"get \"/search\", SearchController, :mount\n",
with_pipelines: [:browser],
arg2: web_module,
router: router
)
end
else
route_contents = """
get "/search", SearchController, :mount
post "/ds/:module/:event", StarView.Dispatch, [], alias: false
"""
Igniter.Libs.Phoenix.append_to_scope(
igniter,
"/",
route_contents,
with_pipelines: [:browser],
arg2: web_module,
router: router
)
end
ensure_csrf_rename_plug(igniter, router)
end
defp ensure_csrf_rename_plug(igniter, router) do
{_, source, _zipper} = Igniter.Project.Module.find_module!(igniter, router)
source_str = Rewrite.Source.get(source, :content)
if String.contains?(source_str, "StarView.Plug.RenameCsrfParam") do
igniter
else
Igniter.Project.Module.find_and_update_module!(igniter, router, fn zipper ->
with {:ok, pipeline} <-
Igniter.Code.Function.move_to_function_call(
zipper,
:pipeline,
2,
&Igniter.Code.Function.argument_equals?(&1, 0, :browser)
),
{:ok, pipeline_block} <- Igniter.Code.Common.move_to_do_block(pipeline),
{:ok, protect_from_forgery} <-
Igniter.Code.Function.move_to_function_call_in_current_scope(
pipeline_block,
:plug,
[1, 2],
&Igniter.Code.Function.argument_equals?(&1, 0, :protect_from_forgery)
) do
{:ok,
Igniter.Code.Common.add_code(
protect_from_forgery,
"plug StarView.Plug.RenameCsrfParam",
placement: :before
)}
else
_ ->
{:warning,
"""
Could not add StarView.Plug.RenameCsrfParam to the #{inspect(router)} browser pipeline.
Add it before `plug :protect_from_forgery` manually.
"""}
end
end)
end
end
end
else
defmodule Mix.Tasks.StarView.Setup.SearchController do
@shortdoc "#{__MODULE__.Docs.short_doc()} | Install `igniter` to use"
@moduledoc __MODULE__.Docs.long_doc()
use Mix.Task
@impl Mix.Task
def run(_argv) do
Mix.shell().error("Requires igniter.")
exit({:shutdown, 1})
end
end
end