From eb2f5f40f16a44cddf647d5ef6694d38b010d4d0 Mon Sep 17 00:00:00 2001 From: Zach Daniel Date: Thu, 18 Jul 2024 12:57:40 -0400 Subject: [PATCH] improvement: Add `Ash.Resource.Igniter.domain` to get the domain of a resource fix: properly convert extension string into a module fix: only display available to extend --- .tool-versions | 4 +- lib/ash/changeset/changeset.ex | 2 + lib/ash/resource/igniter.ex | 52 +++++++++++++++++-------- lib/mix/tasks/helpers.ex | 12 ++++-- lib/mix/tasks/patch/ash.patch.extend.ex | 25 ++++++++---- 5 files changed, 67 insertions(+), 28 deletions(-) diff --git a/.tool-versions b/.tool-versions index 18625f11..ce0360e0 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ -erlang 26.0.2 -elixir 1.17.0 +erlang 27.0.1 +elixir 1.17.2-otp-27 diff --git a/lib/ash/changeset/changeset.ex b/lib/ash/changeset/changeset.ex index 18195e19..e6f24d93 100644 --- a/lib/ash/changeset/changeset.ex +++ b/lib/ash/changeset/changeset.ex @@ -3285,6 +3285,8 @@ defmodule Ash.Changeset do end def run_before_transaction_hooks(changeset) do + warn_on_transaction_hooks(changeset, changeset.before_transaction, "before_transaction") + Enum.reduce_while( changeset.before_transaction, set_phase(changeset, :before_transaction), diff --git a/lib/ash/resource/igniter.ex b/lib/ash/resource/igniter.ex index 56a826bc..3b7ee339 100644 --- a/lib/ash/resource/igniter.ex +++ b/lib/ash/resource/igniter.ex @@ -3,24 +3,44 @@ defmodule Ash.Resource.Igniter do @doc "List all resource modules found in the project" def list_resources(igniter) do + Igniter.Code.Module.find_all_matching_modules(igniter, fn _mod, zipper -> + zipper + |> Igniter.Code.Module.move_to_use(resource_mods()) + |> case do + {:ok, _} -> + true + + _ -> + false + end + end) + end + + @doc "Gets the domain from the given resource module" + @spec domain(Igniter.t(), Ash.Resource.t()) :: + {:ok, Igniter.t(), Ash.Domain.t()} | {:error, Igniter.t()} + def domain(igniter, resource) do + with {:ok, {igniter, _source, zipper}} <- + Igniter.Code.Module.find_module(igniter, resource), + {:ok, zipper} <- Igniter.Code.Common.move_to_do_block(zipper), + {:ok, zipper} <- + Igniter.Code.Module.move_to_use(zipper, resource_mods()), + {:ok, zipper} <- + Igniter.Code.Function.move_to_nth_argument(zipper, 1), + {:ok, zipper} <- Igniter.Code.Keyword.get_key(zipper, :domain), + module when not is_nil(module) <- + Igniter.Code.Module.to_module_name(zipper.node) do + {:ok, igniter, module} + else + _ -> + :error + end + end + + def resource_mods do app_name = Igniter.Project.Application.app_name() - resources = - [Ash.Resource | List.wrap(Application.get_env(app_name, :base_resources))] - - Igniter.Code.Module.find_all_matching_modules(igniter, fn _mod, zipper -> - Enum.any?(resources, fn resource -> - zipper - |> Igniter.Code.Module.move_to_use(resource) - |> case do - {:ok, _} -> - true - - _ -> - false - end - end) - end) + [Ash.Resource | List.wrap(Application.get_env(app_name, :base_resources))] end @doc "Adds the given code block to the resource's `attributes` block" diff --git a/lib/mix/tasks/helpers.ex b/lib/mix/tasks/helpers.ex index a99b3ccc..849d1173 100644 --- a/lib/mix/tasks/helpers.ex +++ b/lib/mix/tasks/helpers.ex @@ -50,9 +50,15 @@ defmodule Ash.Mix.Tasks.Helpers do fn app -> app |> :application.get_key(:modules) - |> elem(1) - |> List.wrap() - |> Enum.filter(&Spark.implements_behaviour?(&1, Spark.Dsl.Extension)) + |> case do + :undefined -> + [] + + {_, mods} -> + mods + |> List.wrap() + |> Enum.filter(&Spark.implements_behaviour?(&1, Spark.Dsl.Extension)) + end end, timeout: :infinity ) diff --git a/lib/mix/tasks/patch/ash.patch.extend.ex b/lib/mix/tasks/patch/ash.patch.extend.ex index 95b6a1f4..3aa09f1a 100644 --- a/lib/mix/tasks/patch/ash.patch.extend.ex +++ b/lib/mix/tasks/patch/ash.patch.extend.ex @@ -138,7 +138,7 @@ defmodule Mix.Tasks.Ash.Patch.Extend do if is_function(extension) do {extension, install} else - Module.concat([extension]) + extension = Module.concat([extension]) if Code.ensure_loaded?(extension) do fun = @@ -156,11 +156,11 @@ defmodule Mix.Tasks.Ash.Patch.Extend do extensions = Enum.map(Ash.Mix.Tasks.Helpers.extensions!([]), &inspect/1) short_codes = [ - "json_api", - "postgres", - "graphql", - "mysql", - "sqlite", + {AshJsonApi.Resource, "json_api"}, + {AshPostgres.DataLayer, "postgres"}, + {AshGraphql.Resource, "graphql"}, + {AshMySql.DataLayer, "mysql"}, + {AshSqlite.DataLayer, "sqlite"}, "ets", "mnesia", "embedded" @@ -169,7 +169,18 @@ defmodule Mix.Tasks.Ash.Patch.Extend do installable = short_codes |> Enum.concat(extensions) - |> Enum.map_join("\n", &" * #{&1}") + |> Enum.flat_map(fn + {dependency, name} -> + if Code.ensure_loaded?(dependency) do + [" * #{name}"] + else + [] + end + + dependency -> + [" * #{dependency}"] + end) + |> Enum.join("\n") {:error, """