ash_graphql/lib/domain/transformers/validate_compatible_names.ex

73 lines
2.1 KiB
Elixir
Raw Normal View History

defmodule AshGraphql.Domain.Transformers.ValidateCompatibleNames do
# Ensures that all field names are valid or remapped to something valid exist
@moduledoc false
use Spark.Dsl.Transformer
alias Spark.Dsl.Transformer
def after_compile?, do: true
def transform(dsl) do
dsl
|> Transformer.get_entities([:graphql, :queries])
|> Enum.concat(Transformer.get_entities(dsl, [:graphql, :mutations]))
|> Enum.each(fn query_or_mutation ->
argument_names = AshGraphql.Resource.Info.argument_names(query_or_mutation.resource)
action = Ash.Resource.Info.action(query_or_mutation.resource, query_or_mutation.action)
Enum.each(action.arguments, fn argument ->
name = argument_names[action.name][argument.name] || argument.name
if invalid_name?(name) do
raise_invalid_argument_name_error(
query_or_mutation.resource,
action,
argument.name,
name
)
end
end)
end)
{:ok, dsl}
end
defp invalid_name?(name) do
Regex.match?(~r/_+\d/, to_string(name))
end
defp raise_invalid_argument_name_error(resource, action, argument_name, name) do
path = [:actions, action.type, action.name, :argument, argument_name]
raise Spark.Error.DslError,
module: resource,
path: path,
message: """
Name #{name} is invalid.
Due to issues in the underlying tooling with camel/snake case conversion of names that
include underscores immediately preceding integers, a different name must be provided to
use in the graphql. To do so, add a mapping in your configured argument_names, i.e
graphql do
...
argument_names #{action.name}: [#{argument_name}: :#{make_name_better(name)}]
...
end
For more information on the underlying issue, see: https://github.com/absinthe-graphql/absinthe/issues/601
"""
end
defp make_name_better(name) do
name
|> to_string()
|> String.replace(~r/_+\d/, fn v ->
String.trim_leading(v, "_")
end)
end
end