Packages
ash_graphql
1.10.0
1.10.0
1.9.4
1.9.3
1.9.2
1.9.1
1.9.0
1.8.5
1.8.4
1.8.3
1.8.2
1.8.1
1.8.0
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.0
1.5.1
1.5.0
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.2.1
1.2.0
1.1.1
1.1.0
1.0.1
1.0.0
1.0.0-rc.5
1.0.0-rc.4
retired
1.0.0-rc.3
1.0.0-rc.2
1.0.0-rc.1
1.0.0-rc.0
0.28.1
0.28.0
0.27.1
0.27.0
0.26.9
0.26.8
0.26.7
0.26.6
0.26.5
0.26.4
0.26.3
0.26.2
0.26.0
0.25.13
0.25.12
0.25.10
0.25.9
0.25.8
0.25.7
0.25.6
0.25.5
0.25.4
0.25.3
0.25.2
0.25.1
0.25.0
0.24.1
0.24.0
0.23.3
0.23.2
0.23.1
0.23.0
0.22.13
0.22.12
0.22.11
0.22.10
0.22.9
0.22.8
0.22.7
0.22.6
0.22.4
0.22.3
0.22.2
0.22.1
0.22.0
0.21.0
retired
0.20.5
0.20.4
0.20.3
0.20.2
0.20.1
0.20.0-rc.3
0.20.0-rc.2
0.20.0-rc.1
0.20.0-rc.0
0.19.0
0.18.0-rc0
0.17.5
0.17.5-rc0
0.17.4
0.17.2
0.17.1
0.17.0
0.16.28
0.16.27
0.16.26
0.16.25
0.16.24
0.16.23
0.16.22
0.16.21
0.16.20
0.16.18-rc5
0.16.18-rc4
0.16.18-rc3
0.16.18-rc2
0.16.18-rc1
0.16.18-rc0
0.16.17
0.16.16
0.16.15
0.16.14
0.16.13
0.16.12
0.16.11
0.16.10
0.16.9
0.16.8
0.16.7
0.16.6
0.16.5
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.10
0.15.9
0.15.8
0.15.7
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.1
0.14.0
0.13.1
0.13.0
0.12.5
0.12.4
0.12.3
0.12.1
0.12.0
0.10.0
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.0
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.3
0.6.2
0.6.1
0.6.0
0.5.0
0.4.0
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.3
0.1.2
The extension for building GraphQL APIs with Ash
Current section
Files
Jump to
Current section
Files
lib/resource/transformers/flatten_query_mutation_groups.ex
# SPDX-FileCopyrightText: 2020 ash_graphql contributors <https://github.com/ash-project/ash_graphql/graphs/contributors>
#
# SPDX-License-Identifier: MIT
defmodule AshGraphql.Resource.Transformers.FlattenQueryMutationGroups do
@moduledoc false
use Spark.Dsl.Transformer
alias AshGraphql.Resource.{Action, Mutation, MutationGroup, Query, QueryGroup}
alias Spark.Dsl.Extension
alias Spark.Dsl.Transformer
def transform(dsl) do
module = Transformer.get_persisted(dsl, :module)
dsl =
dsl
|> replace_section_entities!([:graphql, :queries], &flatten_queries(&1, module))
|> replace_section_entities!([:graphql, :mutations], &flatten_mutations(&1, module))
{:ok, dsl}
end
# Spark keeps each DSL section at `dsl[path]` as `%{entities: [...], opts: [...], ...}`.
# `Transformer.get_entities/2` and `Map.update/4` match how `add_entity/3` and `get_entities/2`
# are implemented in Spark — we only replace `:entities` and preserve opts/annotations.
defp replace_section_entities!(dsl, path, fun) do
entities = Transformer.get_entities(dsl, path)
new_entities = fun.(entities)
Map.update(
dsl,
path,
Map.put(Extension.default_section_config(), :entities, new_entities),
fn config -> %{config | entities: new_entities} end
)
end
defp flatten_queries(entities, module) do
entities
|> Enum.flat_map(&expand_query_entity(&1, module))
|> tap(&assert_unique_grouped_names!(&1, module, :queries))
end
defp flatten_mutations(entities, module) do
entities
|> Enum.flat_map(&expand_mutation_entity(&1, module))
|> tap(&assert_unique_grouped_names!(&1, module, :mutations))
end
defp expand_query_entity(%QueryGroup{} = g, module) do
Enum.map(g.queries, fn
%QueryGroup{} ->
raise Spark.Error.DslError,
module: module,
message:
"Nested `group` inside `queries` is not supported (only one level of grouping is allowed)."
%MutationGroup{} ->
raise Spark.Error.DslError,
module: module,
message: "Mutation `group` cannot appear inside a query `group`."
%Query{} = q ->
%{q | group: g.name}
%Action{} = a ->
%{a | group: g.name}
other ->
raise Spark.Error.DslError,
module: module,
message:
"Unexpected entity inside query `group` (expected get/read_one/list/action): #{inspect(other.__struct__)}"
end)
end
defp expand_query_entity(%Query{} = q, _), do: [q]
defp expand_query_entity(%Action{} = q, _), do: [q]
defp expand_query_entity(other, module) do
raise Spark.Error.DslError,
module: module,
message: "Unexpected entity in queries section: #{inspect(other.__struct__)}"
end
defp expand_mutation_entity(%MutationGroup{} = g, module) do
Enum.map(g.mutations, fn
%MutationGroup{} ->
raise Spark.Error.DslError,
module: module,
message:
"Nested `group` inside `mutations` is not supported (only one level of grouping is allowed)."
%QueryGroup{} ->
raise Spark.Error.DslError,
module: module,
message: "Query `group` cannot appear inside a mutation `group`."
%Mutation{} = m ->
%{m | group: g.name}
%Action{} = a ->
%{a | group: g.name}
other ->
raise Spark.Error.DslError,
module: module,
message:
"Unexpected entity inside mutation `group` (expected create/update/destroy/action): #{inspect(other.__struct__)}"
end)
end
defp expand_mutation_entity(%Mutation{} = m, _), do: [m]
defp expand_mutation_entity(%Action{} = m, _), do: [m]
defp expand_mutation_entity(other, module) do
raise Spark.Error.DslError,
module: module,
message: "Unexpected entity in mutations section: #{inspect(other.__struct__)}"
end
defp assert_unique_grouped_names!(entities, module, :queries) do
entities
|> Enum.filter(&(match?(%Query{}, &1) or match?(%Action{}, &1)))
|> Enum.group_by(fn q -> {q.group, q.name} end)
|> Enum.each(fn
{{nil, _}, _} ->
:ok
{{group, name}, list} ->
if length(list) > 1 do
raise Spark.Error.DslError,
module: module,
message:
"Duplicate GraphQL query field `#{name}` inside query group `#{inspect(group)}`. " <>
"Merged groups (same name) cannot expose the same field name twice."
end
end)
end
defp assert_unique_grouped_names!(entities, module, :mutations) do
entities
|> Enum.filter(&(match?(%Mutation{}, &1) or match?(%Action{}, &1)))
|> Enum.group_by(fn m -> {m.group, m.name} end)
|> Enum.each(fn
{{nil, _}, _} ->
:ok
{{group, name}, list} ->
if length(list) > 1 do
raise Spark.Error.DslError,
module: module,
message:
"Duplicate GraphQL mutation field `#{name}` inside mutation group `#{inspect(group)}`. " <>
"Merged groups (same name) cannot expose the same field name twice."
end
end)
end
end