Packages
absinthe
1.9.1
1.11.0
1.10.2
1.10.1
1.10.0
1.9.1
1.9.0
1.8.0
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.8
1.6.7
retired
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.6.0-rc.1
1.6.0-rc.0
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.5.0-rc.5
1.5.0-rc.4
1.5.0-rc.3
1.5.0-rc.2
1.5.0-rc.1
1.5.0-rc.0
1.5.0-beta.2
1.5.0-beta.1
1.5.0-beta.0
1.5.0-alpha.4
1.5.0-alpha.3
1.5.0-alpha.2
1.5.0-alpha.1
1.5.0-alpha.0
1.4.16
1.4.15
1.4.14
1.4.13
1.4.12
1.4.11
1.4.10
1.4.9
1.4.8
retired
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.4.0-rc.3
1.4.0-rc.2
1.4.0-rc.1
1.4.0-rc.0
1.4.0-beta.5
1.4.0-beta.4
1.4.0-beta.3
1.4.0-beta.2
1.4.0-beta.1
1.3.2
1.3.1
1.3.0
1.3.0-rc.0
1.3.0-beta.2
1.3.0-beta.1
1.3.0-beta.0
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.2.0-rc.0
1.2.0-beta.0
1.2.0-alpha0
1.2.0-alpha.2
1.2.0-alpha.1
1.1.11
1.1.10
1.1.9
1.1.8
1.1.7
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.0
0.5.2
0.5.1
0.5.0
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.2.3
0.2.2
0.2.1
0.1.0
GraphQL for Elixir
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/absinthe/phase/schema/mark_referenced.ex
defmodule Absinthe.Phase.Schema.MarkReferenced do
@moduledoc false
use Absinthe.Phase
alias Absinthe.Blueprint.{Schema, TypeReference}
def run(blueprint, _opts) do
%{schema_definitions: [schema]} = blueprint
schema =
Map.update!(
schema,
:type_definitions,
&mark_referenced(&1, schema.directive_definitions, schema.schema_declaration)
)
{:ok, %{blueprint | schema_definitions: [schema]}}
end
defp mark_referenced(type_defs, directive_defs, schema_declaration) do
types_by_ref =
Enum.reduce(type_defs, %{}, fn type_def, acc ->
acc
|> Map.put(type_def.identifier, type_def)
|> Map.put(type_def.name, type_def)
end)
referenced_type_ids =
schema_declaration.field_definitions
|> Enum.map(&Map.get(types_by_ref, &1.identifier))
|> Enum.reject(&is_nil/1)
|> Enum.concat(directive_defs)
|> Enum.reduce(MapSet.new(), &referenced_types(&1, types_by_ref, &2))
for type <- type_defs do
if type.identifier in referenced_type_ids do
put_in(type.__private__[:__absinthe_referenced__], true)
else
type
end
end
end
defp referenced_types(%Schema.InputValueDefinition{type: type}, types, acc) do
referenced_types(type, types, acc)
end
defp referenced_types(%Schema.DirectiveDefinition{} = type, types, acc) do
type.arguments
|> Enum.reduce(acc, &referenced_types(&1, types, &2))
end
defp referenced_types(%Schema.EnumTypeDefinition{identifier: identifier}, _types, acc) do
MapSet.put(acc, identifier)
end
defp referenced_types(%Schema.FieldDefinition{} = field, types, acc) do
acc =
field.arguments
|> Enum.reduce(acc, &referenced_types(&1, types, &2))
referenced_types(field.type, types, acc)
end
defp referenced_types(
%Schema.InputObjectTypeDefinition{identifier: identifier} = input_object,
types,
acc
) do
if identifier in acc do
acc
else
acc = MapSet.put(acc, identifier)
input_object.fields
|> Enum.reduce(acc, &referenced_types(&1, types, &2))
end
end
defp referenced_types(
%Schema.InterfaceTypeDefinition{identifier: identifier} = interface,
schema,
acc
) do
if identifier in acc do
acc
else
acc = MapSet.put(acc, identifier)
acc =
interface
|> Schema.InterfaceTypeDefinition.find_implementors(Map.values(schema))
|> Enum.reduce(acc, &referenced_types(&1, schema, &2))
interface.fields
|> Enum.reduce(acc, &referenced_types(&1, schema, &2))
end
end
defp referenced_types(%TypeReference.List{of_type: inner_type}, schema, acc) do
referenced_types(inner_type, schema, acc)
end
defp referenced_types(%TypeReference.NonNull{of_type: inner_type}, schema, acc) do
referenced_types(inner_type, schema, acc)
end
defp referenced_types(
%Schema.ObjectTypeDefinition{identifier: identifier} = object,
schema,
acc
) do
if identifier in acc do
acc
else
acc = MapSet.put(acc, identifier)
acc =
object.fields
|> Enum.reduce(acc, &referenced_types(&1, schema, &2))
object.interfaces
|> Enum.reduce(acc, &referenced_types(&1, schema, &2))
end
end
defp referenced_types(%Schema.ScalarTypeDefinition{identifier: identifier}, _schema, acc) do
MapSet.put(acc, identifier)
end
defp referenced_types(%Schema.UnionTypeDefinition{identifier: identifier} = union, schema, acc) do
if identifier in acc do
acc
else
acc = MapSet.put(acc, identifier)
union.types
|> Enum.reduce(acc, &referenced_types(&1, schema, &2))
end
end
defp referenced_types(%TypeReference.Identifier{} = ref, schema, acc) do
referenced_types(Map.fetch!(schema, ref.id), schema, acc)
end
defp referenced_types(%TypeReference.Name{} = ref, schema, acc) do
referenced_types(Map.fetch!(schema, ref.name), schema, acc)
end
defp referenced_types(type, schema, acc) when is_atom(type) and type != nil do
referenced_types(Map.fetch!(schema, type), schema, acc)
end
end