mirror of
https://github.com/ash-project/ash_graphql.git
synced 2024-09-20 13:24:14 +12:00
148 lines
4.5 KiB
Elixir
148 lines
4.5 KiB
Elixir
defmodule Mix.Tasks.AshGraphql.Install do
|
|
@moduledoc "Installs AshGraphql. Should be run with `mix igniter.install ash_postgres`"
|
|
@shortdoc @moduledoc
|
|
require Igniter.Code.Common
|
|
use Igniter.Mix.Task
|
|
|
|
def igniter(igniter, _argv) do
|
|
igniter =
|
|
igniter
|
|
|> Igniter.Project.Formatter.import_dep(:ash_graphql)
|
|
|> Spark.Igniter.prepend_to_section_order(:"Ash.Resource", [:graphql])
|
|
|> Spark.Igniter.prepend_to_section_order(:"Ash.Domain", [:graphql])
|
|
|
|
schema_name = Igniter.Code.Module.module_name("GraphqlSchema")
|
|
|
|
{igniter, candidate_ash_graphql_schemas} =
|
|
Igniter.Code.Module.find_all_matching_modules(igniter, fn _name, zipper ->
|
|
zipper
|
|
|> Igniter.Code.Module.move_to_use(AshGraphql)
|
|
end)
|
|
|
|
if Enum.empty?(candidate_ash_graphql_schemas) do
|
|
igniter
|
|
|> setup_absinthe_schema(schema_name)
|
|
|> setup_web(schema_name)
|
|
else
|
|
igniter
|
|
|> Igniter.add_warning("AshGraphql schema already exists, skipping installation.")
|
|
end
|
|
end
|
|
|
|
defp setup_web(igniter, schema_name) do
|
|
case Igniter.Libs.Phoenix.select_router(igniter) do
|
|
{igniter, nil} ->
|
|
igniter
|
|
|> Igniter.add_warning("""
|
|
No Phoenix router found, skipping phoenix installation.
|
|
|
|
See the getting started guide for instructions on installing AshGraphql with `plug`.
|
|
If you have yet to set up phoenix, you'll have to do that manually and then rerun this installer.
|
|
""")
|
|
|
|
{igniter, router} ->
|
|
igniter
|
|
|> Igniter.Libs.Phoenix.add_pipeline(:graphql, "plug AshGraphql.Plug", router: router)
|
|
|> Igniter.Libs.Phoenix.add_scope(
|
|
"/gql",
|
|
"""
|
|
pipe_through [:graphql]
|
|
|
|
forward "/playground",
|
|
Absinthe.Plug.GraphiQL,
|
|
schema: Module.concat(["#{inspect(schema_name)}"]),
|
|
interface: :playground
|
|
|
|
forward "/",
|
|
Absinthe.Plug,
|
|
schema: Module.concat(["#{inspect(schema_name)}"])
|
|
""",
|
|
router: router
|
|
)
|
|
end
|
|
end
|
|
|
|
defp setup_absinthe_schema(igniter, schema_name) do
|
|
{igniter, domains} = Ash.Domain.Igniter.list_domains(igniter)
|
|
{igniter, resources} = Ash.Resource.Igniter.list_resources(igniter)
|
|
|
|
{igniter, any_queries?} =
|
|
Enum.reduce_while(
|
|
Enum.map(resources, &{&1, [2, 3]}) ++ Enum.map(domains, &{&1, [3, 4]}),
|
|
{igniter, false},
|
|
fn {mod, arities}, {igniter, false} ->
|
|
with {:ok, {igniter, _source, zipper}} <-
|
|
Igniter.Code.Module.find_module(igniter, mod),
|
|
{:ok, zipper} <-
|
|
Igniter.Code.Function.move_to_function_call_in_current_scope(
|
|
zipper,
|
|
:graphql,
|
|
1
|
|
),
|
|
{:ok, zipper} <- Igniter.Code.Common.move_to_do_block(zipper),
|
|
{:ok, zipper} <-
|
|
Igniter.Code.Function.move_to_function_call_in_current_scope(
|
|
zipper,
|
|
:queries,
|
|
1
|
|
),
|
|
{:ok, zipper} <- Igniter.Code.Common.move_to_do_block(zipper) do
|
|
has_query? =
|
|
Enum.any?([:get, :read_one, :list, :action], fn query_name ->
|
|
match?(
|
|
{:ok, _},
|
|
Igniter.Code.Function.move_to_function_call_in_current_scope(
|
|
zipper,
|
|
query_name,
|
|
arities
|
|
)
|
|
)
|
|
end)
|
|
|
|
if has_query? do
|
|
{:halt, {igniter, true}}
|
|
else
|
|
{:cont, {igniter, false}}
|
|
end
|
|
else
|
|
_ ->
|
|
{:cont, {igniter, false}}
|
|
end
|
|
end
|
|
)
|
|
|
|
placeholder_query =
|
|
unless any_queries? do
|
|
"""
|
|
@desc "Remove me once you have a query of your own!"
|
|
field :remove_me, :string do
|
|
resolve fn _, _, _ ->
|
|
{:ok, "Remove me!"}
|
|
end
|
|
end
|
|
"""
|
|
end
|
|
|
|
igniter
|
|
|> Igniter.Code.Module.find_and_update_or_create_module(
|
|
schema_name,
|
|
"""
|
|
use Absinthe.Schema
|
|
use AshGraphql, domains: #{inspect(domains)}
|
|
|
|
query do
|
|
# Custom absinthe queries can be placed here
|
|
#{placeholder_query}
|
|
end
|
|
|
|
mutation do
|
|
# Custom absinthe mutations can be placed here
|
|
end
|
|
""",
|
|
fn zipper ->
|
|
# Should never get here
|
|
{:ok, zipper}
|
|
end
|
|
)
|
|
end
|
|
end
|