interfaces_must_resolve_types.ex (2106B)
1 defmodule Absinthe.Phase.Schema.Validation.InterfacesMustResolveTypes do 2 @moduledoc false 3 4 use Absinthe.Phase 5 alias Absinthe.Blueprint 6 7 def run(bp, _) do 8 bp = Blueprint.prewalk(bp, &handle_schemas/1) 9 {:ok, bp} 10 end 11 12 defp handle_schemas(%Blueprint.Schema.SchemaDefinition{} = schema) do 13 implementors = 14 schema.type_definitions 15 |> Enum.filter(&match?(%Blueprint.Schema.ObjectTypeDefinition{}, &1)) 16 |> Enum.flat_map(fn obj -> 17 for iface <- obj.interfaces do 18 {iface, obj} 19 end 20 end) 21 |> Enum.group_by(fn {iface, _obj} -> iface end, fn {_iface, obj} -> obj end) 22 23 schema = Blueprint.prewalk(schema, &validate_interface(&1, implementors)) 24 {:halt, schema} 25 end 26 27 defp handle_schemas(obj) do 28 obj 29 end 30 31 defp validate_interface(%Blueprint.Schema.InterfaceTypeDefinition{} = iface, implementors) do 32 resolve_type = Absinthe.Type.function(iface, :resolve_type) 33 34 if(resolve_type || all_objects_is_type_of?(iface, implementors)) do 35 iface 36 else 37 iface |> put_error(error(iface)) 38 end 39 end 40 41 defp validate_interface(type, _) do 42 type 43 end 44 45 defp all_objects_is_type_of?(iface, implementors) do 46 implementors 47 |> Map.get(iface.identifier, []) 48 |> Enum.all?(&Absinthe.Type.function(&1, :is_type_of)) 49 end 50 51 defp error(interface) do 52 %Absinthe.Phase.Error{ 53 message: explanation(interface.identifier), 54 locations: [interface.__reference__.location], 55 phase: __MODULE__, 56 extra: interface.identifier 57 } 58 end 59 60 @description """ 61 An interface must be able to resolve the implementing types of results. 62 63 > The interface type should have some way of determining which object a given 64 > result corresponds to. 65 66 Reference: https://github.com/facebook/graphql/blob/master/spec/Section%203%20--%20Type%20System.md#interfaces 67 """ 68 69 def explanation(interface) do 70 """ 71 Interface type "#{interface}" either: 72 * Does not have a `resolve_type` function. 73 * Is missing a `is_type_of` function on all implementing types. 74 75 #{@description} 76 """ 77 end 78 end