improvement: registry resource validations transformers -> verifiers

improvement: better error message on unknown relationship
This commit is contained in:
Zach Daniel 2023-01-30 16:10:15 -05:00
parent 227344631f
commit ce6b44525f
5 changed files with 55 additions and 76 deletions

View file

@ -2,11 +2,12 @@ defmodule Ash.Registry.ResourceValidations do
@moduledoc """
Adds some top level validations of resources present in a registry
"""
@transformers [
Ash.Registry.ResourceValidations.Transformers.EnsureResourcesCompiled,
Ash.Registry.ResourceValidations.Transformers.ValidateRelatedResourceInclusion,
Ash.Registry.ResourceValidations.Transformers.EnsureNoEmbeds
@verifiers [
Ash.Registry.ResourceValidations.Verifiers.EnsureResourcesCompiled,
Ash.Registry.ResourceValidations.Verifiers.ValidateRelatedResourceInclusion,
Ash.Registry.ResourceValidations.Verifiers.EnsureNoEmbeds
]
use Spark.Dsl.Extension, transformers: @transformers
use Spark.Dsl.Extension, verifiers: @verifiers
end

View file

@ -1,51 +0,0 @@
defmodule Ash.Registry.ResourceValidations.Transformers.ValidateRelatedResourceInclusion do
@moduledoc """
Ensures that all related resources are included in an API.
"""
use Spark.Dsl.Transformer
alias Spark.Dsl.Transformer
@impl true
def after_compile?, do: true
@impl true
def after?(Ash.Registry.ResourceValidations.Transformers.EnsureResourcesCompiled), do: true
def after?(_), do: false
@impl true
def transform(dsl) do
resources =
dsl
|> Transformer.get_entities([:entries])
|> Enum.map(& &1.entry)
resources
|> Enum.flat_map(&get_all_related_resources(&1, resources))
|> Enum.uniq()
|> Enum.reject(&(&1 in resources))
|> case do
[] ->
{:ok, dsl}
resources ->
raise "Resources #{Enum.map_join(resources, ", ", &inspect/1)} must be included in the registry."
end
end
defp get_all_related_resources(resource, checked) do
resource
|> Ash.Resource.Info.relationships()
|> Enum.reject(& &1.api)
|> Enum.flat_map(fn
%{type: :many_to_many} = relationship ->
[relationship.through, relationship.destination]
relationship ->
[relationship.destination]
end)
|> Enum.reject(&(&1 in checked))
|> Enum.flat_map(fn resource ->
[resource | get_all_related_resources(resource, [resource | checked])]
end)
end
end

View file

@ -1,22 +1,19 @@
defmodule Ash.Registry.ResourceValidations.Transformers.EnsureNoEmbeds do
defmodule Ash.Registry.ResourceValidations.Verifiers.EnsureNoEmbeds do
@moduledoc """
Ensures that all resources for a given registry are not embeds.
"""
use Spark.Dsl.Transformer
alias Spark.Dsl.Transformer
use Spark.Dsl.Verifier
alias Spark.Dsl.Verifier
@impl true
def after_compile?, do: true
@impl true
def transform(dsl) do
def verify(dsl) do
dsl
|> Transformer.get_entities([:entries])
|> Verifier.get_entities([:entries])
|> Enum.map(& &1.entry)
|> Enum.filter(&Ash.Resource.Info.embedded?/1)
|> case do
[] ->
{:ok, dsl}
:ok
rejected ->
{:error,

View file

@ -1,19 +1,15 @@
defmodule Ash.Registry.ResourceValidations.Transformers.EnsureResourcesCompiled do
defmodule Ash.Registry.ResourceValidations.Verifiers.EnsureResourcesCompiled do
@moduledoc """
Ensures that all resources for a given registry are compiled.
"""
use Spark.Dsl.Transformer
alias Spark.Dsl.Transformer
use Spark.Dsl.Verifier
alias Spark.Dsl.Verifier
require Logger
@impl true
def after_compile?, do: true
@impl true
def transform(dsl) do
def verify(dsl) do
dsl
|> Transformer.get_entities([:entries])
|> Verifier.get_entities([:entries])
|> Enum.map(& &1.entry)
|> Enum.map(fn resource ->
try do
@ -37,7 +33,7 @@ defmodule Ash.Registry.ResourceValidations.Transformers.EnsureResourcesCompiled
|> Enum.filter(& &1)
|> case do
[] ->
{:ok, dsl}
:ok
rejected ->
for {resource, error} <- rejected do
@ -46,7 +42,7 @@ defmodule Ash.Registry.ResourceValidations.Transformers.EnsureResourcesCompiled
)
end
{:ok, dsl}
:ok
end
end
end

View file

@ -0,0 +1,36 @@
defmodule Ash.Registry.ResourceValidations.Verifiers.ValidateRelatedResourceInclusion do
@moduledoc """
Ensures that all related resources are included in an API.
"""
use Spark.Dsl.Verifier
alias Spark.Dsl.Verifier
@impl true
def verify(dsl) do
resources =
dsl
|> Verifier.get_entities([:entries])
|> Enum.map(& &1.entry)
for resource <- resources do
for relationship <- Ash.Resource.Info.relationships(resource) do
unless relationship.api || relationship.destination in resources do
raise """
Could not determine api for #{inspect(resource)}.#{relationship.name}. Please do one of the following:
1. Add the resource to the registry `#{Verifier.get_persisted(dsl, :module)}`
2. Set the `api` option on the relationship, for example:
#{relationship.type} :#{relationship.name}, #{inspect(relationship.destination)} do
api SomeOtherApi
end
"""
end
end
end
:ok
end
end