Skip to content

Commit

Permalink
improvement: add mix ash_postgres.install (mix igniter.install ash_…
Browse files Browse the repository at this point in the history
…postgres)
  • Loading branch information
zachdaniel committed Jun 21, 2024
1 parent 4627952 commit 6b1f6ba
Show file tree
Hide file tree
Showing 9 changed files with 375 additions and 37 deletions.
4 changes: 2 additions & 2 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
erlang 26.2.2
elixir 1.16.2
erlang 27.0
elixir 1.17.0
20 changes: 20 additions & 0 deletions lib/data_layer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,8 @@ defmodule AshPostgres.DataLayer do
A postgres data layer that leverages Ecto's postgres capabilities.
"""

require Igniter.Code.Common

use Spark.Dsl.Extension,
sections: @sections,
verifiers: [
Expand Down Expand Up @@ -2919,6 +2921,24 @@ defmodule AshPostgres.DataLayer do
end
end

if Code.ensure_loaded?(Igniter) do
def install(igniter, module, Ash.Resource, path, _argv) do
table_name =
module
|> Module.split()
|> List.last()
|> Macro.underscore()

repo = Igniter.Code.Module.module_name("Repo")

igniter
|> Spark.Igniter.set_option(Ash.Resource, path, [:postgres, :table], table_name)
|> Spark.Igniter.set_option(Ash.Resource, path, [:postgres, :repo], repo)
end

def install(igniter, _, _, _), do: igniter
end

@impl true
def rollback(resource, term) do
AshPostgres.DataLayer.Info.repo(resource, :mutate).rollback(term)
Expand Down
9 changes: 9 additions & 0 deletions lib/migration_generator/migration_generator.ex
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ defmodule AshPostgres.MigrationGenerator do
repos =
(snapshots ++ tenant_snapshots)
|> Enum.map(& &1.repo)
|> Enum.concat(find_repos())
|> Enum.uniq()

Mix.shell().info("\nExtension Migrations: ")
Expand All @@ -55,6 +56,14 @@ defmodule AshPostgres.MigrationGenerator do
create_migrations(snapshots, opts, false)
end

defp find_repos do
Mix.Project.config()[:app]
|> Application.get_env(:ecto_repos, [])
|> Enum.filter(fn repo ->
Spark.implements_behaviour?(repo, AshPostgres.Repo)
end)
end

@doc """
A work in progress utility for getting snapshots.
Expand Down
77 changes: 46 additions & 31 deletions lib/mix/helpers.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
defmodule AshPostgres.Mix.Helpers do
@moduledoc false
def domains!(opts, args) do
def domains!(opts, args, error_on_no_domains? \\ true) do
apps =
if apps_paths = Mix.Project.apps_paths() do
apps_paths |> Map.keys() |> Enum.sort()
Expand Down Expand Up @@ -30,51 +30,66 @@ defmodule AshPostgres.Mix.Helpers do
|> Enum.map(&ensure_compiled(&1, args))
|> case do
[] ->
raise "must supply the --domains argument, or set `config :my_app, ash_domains: [...]` in config"
if error_on_no_domains? do
raise "must supply the --domains argument, or set `config :my_app, ash_domains: [...]` in config"
else
[]
end

domains ->
domains
end
end

def repos!(opts, args) do
domains = domains!(opts, args)
if opts[:domains] && opts[:domains] != "" do
domains = domains!(opts, args)

resources =
domains
|> Enum.flat_map(&Ash.Domain.Info.resources/1)
|> Enum.filter(&(Ash.DataLayer.data_layer(&1) == AshPostgres.DataLayer))
resources =
domains
|> Enum.flat_map(&Ash.Domain.Info.resources/1)
|> Enum.filter(&(Ash.DataLayer.data_layer(&1) == AshPostgres.DataLayer))
|> case do
[] ->
raise """
No resources with `data_layer: AshPostgres.DataLayer` found in the domains #{Enum.map_join(domains, ",", &inspect/1)}.
Must be able to find at least one resource with `data_layer: AshPostgres.DataLayer`.
"""

resources ->
resources
end

resources
|> Enum.flat_map(
&[
AshPostgres.DataLayer.Info.repo(&1, :read),
AshPostgres.DataLayer.Info.repo(&1, :mutate)
]
)
|> Enum.uniq()
|> case do
[] ->
raise """
No resources with `data_layer: AshPostgres.DataLayer` found in the domains #{Enum.map_join(domains, ",", &inspect/1)}.
Must be able to find at least one resource with `data_layer: AshPostgres.DataLayer`.
"""
No repos could be found configured on the resources in the domains: #{Enum.map_join(domains, ",", &inspect/1)}
resources ->
resources
end
At least one resource must have a repo configured.
resources
|> Enum.flat_map(
&[AshPostgres.DataLayer.Info.repo(&1, :read), AshPostgres.DataLayer.Info.repo(&1, :mutate)]
)
|> Enum.uniq()
|> case do
[] ->
raise """
No repos could be found configured on the resources in the domains: #{Enum.map_join(domains, ",", &inspect/1)}
The following resources were found with `data_layer: AshPostgres.DataLayer`:
At least one resource must have a repo configured.
The following resources were found with `data_layer: AshPostgres.DataLayer`:
#{Enum.map_join(resources, "\n", &"* #{inspect(&1)}")}
"""
#{Enum.map_join(resources, "\n", &"* #{inspect(&1)}")}
"""

repos ->
repos
repos ->
repos
end
else
Mix.Project.config()[:app]
|> Application.get_env(:ecto_repos, [])
|> Enum.filter(fn repo ->
Spark.implements_behaviour?(repo, AshPostgres.Repo)
end)
end
end

Expand Down
9 changes: 8 additions & 1 deletion lib/mix/tasks/ash_postgres.generate_migrations.ex
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,14 @@ defmodule Mix.Tasks.AshPostgres.GenerateMigrations do
]
)

domains = AshPostgres.Mix.Helpers.domains!(opts, args)
domains = AshPostgres.Mix.Helpers.domains!(opts, args, false)

if Enum.empty?(domains) do
IO.warn("""
No domains found, so no resource-related migrations will be generated.
Pass the `--domains` option or configure `config :your_app, ash_domains: [...]`
""")
end

opts =
opts
Expand Down
Loading

0 comments on commit 6b1f6ba

Please sign in to comment.