Current section

Files

Jump to
absinthe_federation lib absinthe federation schema phase.ex
Raw

lib/absinthe/federation/schema/phase.ex

defmodule Absinthe.Federation.Schema.Phase do
@moduledoc false
use Absinthe.Phase
alias Absinthe.Blueprint
alias Absinthe.Blueprint.Schema
alias Absinthe.Federation.Schema.Directive
alias Absinthe.Federation.Schema.EntitiesField
alias Absinthe.Federation.Schema.EntityUnion
alias Absinthe.Federation.Schema.ServiceField
alias Absinthe.Type
@dialyzer {:nowarn_function, add_directive: 2}
def run(%Blueprint{} = blueprint, _) do
blueprint = Blueprint.postwalk(blueprint, &collect_types/1)
{:ok, blueprint}
end
@spec collect_types(Blueprint.node_t()) :: Blueprint.node_t()
defp collect_types(%Schema.SchemaDefinition{type_definitions: type_definitions} = node) do
entity_union = EntityUnion.build(node)
%{node | type_definitions: [entity_union | type_definitions]}
end
defp collect_types(%Schema.ObjectTypeDefinition{identifier: :query, fields: fields} = node) do
service_field = ServiceField.build()
entities_field = EntitiesField.build()
%{node | fields: [service_field, entities_field] ++ fields}
end
defp collect_types(%{__private__: _private} = node) do
meta = Type.meta(node)
maybe_add_directives(node, meta)
end
defp collect_types(node), do: node
@spec maybe_add_directives(term(), any()) :: term()
defp maybe_add_directives(node, meta) do
node
|> maybe_add_key_directive(meta)
|> maybe_add_external_directive(meta)
|> maybe_add_requires_directive(meta)
|> maybe_add_provides_directive(meta)
|> maybe_add_extends_directive(meta)
end
@spec maybe_add_key_directive(term(), map()) :: term()
defp maybe_add_key_directive(node, %{key_fields: fields}) do
directive = Directive.build("key", fields: fields)
add_directive(node, directive)
end
defp maybe_add_key_directive(node, _meta), do: node
defp maybe_add_external_directive(node, %{external: true}) do
directive = Directive.build("external")
add_directive(node, directive)
end
defp maybe_add_external_directive(node, _meta), do: node
defp maybe_add_requires_directive(node, %{requires_fields: fields}) do
directive = Directive.build("requires", fields: fields)
add_directive(node, directive)
end
defp maybe_add_requires_directive(node, _meta), do: node
defp maybe_add_provides_directive(node, %{provides_fields: fields}) do
directive = Directive.build("provides", fields: fields)
add_directive(node, directive)
end
defp maybe_add_provides_directive(node, _meta), do: node
defp maybe_add_extends_directive(node, %{extends: true}) do
directive = Directive.build("extends")
add_directive(node, directive)
end
defp maybe_add_extends_directive(node, _meta), do: node
defp add_directive(%{directives: directives} = node, directive) do
%{node | directives: [directive | directives]}
end
defp add_directive(node, _directive), do: node
end