zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

interface.ex (3978B)


      1 defmodule Absinthe.Type.Interface do
      2   @moduledoc """
      3   A defined interface type that represent a list of named fields and their
      4   arguments.
      5 
      6   Fields on an interface have the same rules as fields on an
      7   `Absinthe.Type.Object`.
      8 
      9   If an `Absinthe.Type.Object` lists an interface in its `:interfaces` entry,
     10   it guarantees that it defines the same fields and arguments that the
     11   interface does.
     12 
     13   Because sometimes it's for the interface to determine the implementing type of
     14   a resolved object, you must either:
     15 
     16   * Provide a `:resolve_type` function on the interface
     17   * Provide a `:is_type_of` function on each implementing type
     18 
     19   ```
     20   interface :named_entity do
     21     field :name, :string
     22     resolve_type fn
     23       %{age: _}, _ -> :person
     24       %{employee_count: _}, _ -> :business
     25       _, _ -> nil
     26     end
     27   end
     28 
     29   object :person do
     30     field :name, :string
     31     field :age, :string
     32 
     33     interface :named_entity
     34   end
     35 
     36   object :business do
     37     field :name, :string
     38     field :employee_count, :integer
     39 
     40     interface :named_entity
     41   end
     42   ```
     43   """
     44 
     45   use Absinthe.Introspection.TypeKind, :interface
     46 
     47   alias Absinthe.Type
     48   alias Absinthe.Schema
     49 
     50   @typedoc """
     51   * `:name` - The name of the interface type. Should be a TitleCased `binary`. Set automatically.
     52   * `:description` - A nice description for introspection.
     53   * `:fields` - A map of `Absinthe.Type.Field` structs. See `Absinthe.Schema.Notation.field/4` and
     54   * `:args` - A map of `Absinthe.Type.Argument` structs. See `Absinthe.Schema.Notation.arg/2`.
     55   * `:resolve_type` - A function used to determine the implementing type of a resolved object. See also `Absinthe.Type.Object`'s `:is_type_of`.
     56 
     57   The `:resolve_type` function will be passed two arguments; the object whose type needs to be identified, and the `Absinthe.Execution` struct providing the full execution context.
     58 
     59   The `__private__` and `:__reference__` keys are for internal use.
     60   """
     61   @type t :: %__MODULE__{
     62           name: binary,
     63           description: binary,
     64           fields: map,
     65           identifier: atom,
     66           interfaces: [Absinthe.Type.Interface.t()],
     67           __private__: Keyword.t(),
     68           definition: module,
     69           __reference__: Type.Reference.t()
     70         }
     71 
     72   defstruct name: nil,
     73             description: nil,
     74             fields: nil,
     75             identifier: nil,
     76             resolve_type: nil,
     77             interfaces: [],
     78             __private__: [],
     79             definition: nil,
     80             __reference__: nil
     81 
     82   @doc false
     83   defdelegate functions, to: Absinthe.Blueprint.Schema.InterfaceTypeDefinition
     84 
     85   @spec resolve_type(Type.Interface.t(), any, Absinthe.Resolution.t()) :: Type.t() | nil
     86   def resolve_type(type, obj, env, opts \\ [lookup: true])
     87 
     88   def resolve_type(interface, obj, %{schema: schema} = env, opts) do
     89     if resolver = Type.function(interface, :resolve_type) do
     90       case resolver.(obj, env) do
     91         nil ->
     92           nil
     93 
     94         ident when is_atom(ident) ->
     95           if opts[:lookup] do
     96             Absinthe.Schema.lookup_type(schema, ident)
     97           else
     98             ident
     99           end
    100       end
    101     else
    102       type_name =
    103         Schema.implementors(schema, interface.identifier)
    104         |> Enum.find(fn type ->
    105           Absinthe.Type.function(type, :is_type_of).(obj)
    106         end)
    107 
    108       if opts[:lookup] do
    109         Absinthe.Schema.lookup_type(schema, type_name)
    110       else
    111         type_name
    112       end
    113     end
    114   end
    115 
    116   @doc """
    117   Whether the interface (or implementors) are correctly configured to resolve
    118   objects.
    119   """
    120   @spec type_resolvable?(Schema.t(), t) :: boolean
    121   def type_resolvable?(schema, %{resolve_type: nil} = iface) do
    122     Schema.implementors(schema, iface)
    123     |> Enum.all?(& &1.is_type_of)
    124   end
    125 
    126   def type_resolvable?(_, %{resolve_type: _}) do
    127     true
    128   end
    129 
    130   @doc false
    131   @spec member?(t, Type.t()) :: boolean
    132   def member?(%{identifier: ident}, %{interfaces: ifaces}) do
    133     ident in ifaces
    134   end
    135 
    136   def member?(_, _) do
    137     false
    138   end
    139 end