Packages

An Absinthe extension for composing GraphQL endpoints together

Current section

Files

Jump to
absinthe_compose lib absinthe compose downstream.ex
Raw

lib/absinthe/compose/downstream.ex

defmodule Absinthe.Compose.Downstream do
@moduledoc """
Translates the raw results we get from downstream schemas to a format that our schema can traverse
"""
alias Absinthe.Blueprint.Document.Field
def translate(nil, _field, _schema), do: nil
def translate(downstream, %Field{schema_node: %{type: %Absinthe.Type.List{}}} = field, schema) do
translate_list(downstream, field, schema)
end
def translate(downstream, %Field{selections: []} = field, schema) do
type = Absinthe.Schema.lookup_type(schema, field.schema_node.type)
translate_scalar(downstream, type)
end
def translate(downstream, %Field{} = field, schema) do
translate_object(downstream, field, schema)
end
def translate(downstream, tree, _schema) do
raise "Not sure how to translate #{inspect(downstream)} to #{inspect(tree)}"
end
def translate_list(downstream, field, schema) do
%Absinthe.Type.List{of_type: type_id} = field.schema_node.type
of_type = Absinthe.Schema.lookup_type(schema, type_id)
sub_schema_node = Map.put(field.schema_node, :type, of_type)
item_field = Map.put(field, :schema_node, sub_schema_node)
Enum.map(downstream, &translate(&1, item_field, schema))
end
def translate_object(nil, _list, _schema), do: nil
def translate_object(downstream, field, schema) do
Enum.reduce(field.selections, %{}, fn field, map ->
internal_name = field.schema_node.identifier
raw = Map.get(downstream, field.name)
internal_value = translate(raw, field, schema)
Map.put(map, internal_name, internal_value)
end)
end
def translate_scalar(nil, _), do: nil
def translate_scalar(downstream, %Absinthe.Type.Scalar{identifier: :string}) do
downstream
end
def translate_scalar(downstream, %Absinthe.Type.Scalar{identifier: :id}) do
downstream
end
def translate_scalar(downstream, %Absinthe.Type.Scalar{identifier: :integer}) do
downstream
end
def translate_scalar(downstream, %Absinthe.Type.Enum{} = enum) do
case Map.get(enum.values_by_name, downstream) do
nil -> raise "Invalid Enum value #{inspect(downstream)} for #{enum.name}"
%Absinthe.Type.Enum.Value{value: value} -> value
end
end
def translate_scalar(downstream, type) do
raise "Not sure how to translate #{inspect(downstream)} to #{inspect(type)}"
end
end