zf

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

introspection.ex (4878B)


      1 defmodule Absinthe.Phase.Schema.Introspection do
      2   @moduledoc false
      3 
      4   use Absinthe.Phase
      5   alias Absinthe.Blueprint
      6 
      7   alias Absinthe.Blueprint.Schema.FieldDefinition
      8   alias Absinthe.Blueprint.Schema.InputValueDefinition
      9   alias Absinthe.Blueprint.TypeReference.NonNull
     10   alias Absinthe.Blueprint.Schema.ObjectTypeDefinition
     11   alias Absinthe.Blueprint.Schema.ListTypeDefinition
     12   alias Absinthe.Blueprint.Schema.UnionTypeDefinition
     13   alias Absinthe.Blueprint.Schema.InterfaceTypeDefinition
     14 
     15   def __absinthe_function__(identifier, :middleware) do
     16     [{{Absinthe.Resolution, :call}, resolve_fn(identifier)}]
     17   end
     18 
     19   def run(blueprint, _opts) do
     20     blueprint = attach_introspection_fields(blueprint)
     21     {:ok, blueprint}
     22   end
     23 
     24   @doc """
     25   Append the given field or fields to the given type
     26   """
     27   def attach_introspection_fields(blueprint = %Blueprint{}) do
     28     %{blueprint | schema_definitions: update_schema_defs(blueprint.schema_definitions)}
     29   end
     30 
     31   def update_schema_defs(schema_definitions) do
     32     for schema_def = %{type_definitions: type_defs} <- schema_definitions do
     33       %{schema_def | type_definitions: update_type_defs(type_defs)}
     34     end
     35   end
     36 
     37   def update_type_defs(type_defs) do
     38     for type_def = %struct_type{} <- type_defs do
     39       cond do
     40         type_def.name in ["RootQueryType", "Query"] ->
     41           type_field = field_def(:type)
     42           schema_field = field_def(:schema)
     43           typename_field = field_def(:typename)
     44           %{type_def | fields: [type_field, schema_field, typename_field | type_def.fields]}
     45 
     46         struct_type in [
     47           ObjectTypeDefinition,
     48           ListTypeDefinition,
     49           UnionTypeDefinition,
     50           InterfaceTypeDefinition
     51         ] ->
     52           typename_field = field_def(:typename)
     53           %{type_def | fields: [typename_field | type_def.fields]}
     54 
     55         true ->
     56           type_def
     57       end
     58     end
     59   end
     60 
     61   def field_def(:typename) do
     62     %FieldDefinition{
     63       name: "__typename",
     64       identifier: :__typename,
     65       module: __MODULE__,
     66       type: :string,
     67       description: "The name of the object type currently being queried.",
     68       complexity: 0,
     69       triggers: %{},
     70       middleware: [
     71         {:ref, __MODULE__, :typename}
     72       ],
     73       flags: %{reserved_name: true},
     74       __reference__: Absinthe.Schema.Notation.build_reference(__ENV__)
     75     }
     76   end
     77 
     78   def field_def(:type) do
     79     %FieldDefinition{
     80       __reference__: Absinthe.Schema.Notation.build_reference(__ENV__),
     81       name: "__type",
     82       identifier: :__type,
     83       type: :__type,
     84       module: __MODULE__,
     85       description: "Represents scalars, interfaces, object types, unions, enums in the system",
     86       triggers: %{},
     87       arguments: [
     88         %InputValueDefinition{
     89           __reference__: Absinthe.Schema.Notation.build_reference(__ENV__),
     90           module: __MODULE__,
     91           identifier: :name,
     92           name: "name",
     93           type: %NonNull{of_type: :string},
     94           description: "The name of the type to introspect"
     95         }
     96       ],
     97       middleware: [
     98         {:ref, __MODULE__, :type}
     99       ],
    100       flags: %{reserved_name: true}
    101     }
    102   end
    103 
    104   def field_def(:schema) do
    105     %FieldDefinition{
    106       name: "__schema",
    107       identifier: :__schema,
    108       type: :__schema,
    109       module: __MODULE__,
    110       description: "Represents the schema",
    111       triggers: %{},
    112       middleware: [
    113         {:ref, __MODULE__, :schema}
    114       ],
    115       flags: %{reserved_name: true},
    116       __reference__: Absinthe.Schema.Notation.build_reference(__ENV__)
    117     }
    118   end
    119 
    120   def resolve_fn(:schema) do
    121     fn _, %{schema: schema} ->
    122       {:ok, schema}
    123     end
    124   end
    125 
    126   def resolve_fn(:type) do
    127     fn %{name: name}, %{schema: schema} ->
    128       type_def =
    129         case Absinthe.Schema.lookup_type(schema, name) do
    130           type_def = %{fields: fields} ->
    131             %{type_def | fields: filter_fields(fields)}
    132 
    133           type_def ->
    134             type_def
    135         end
    136 
    137       {:ok, type_def}
    138     end
    139   end
    140 
    141   def resolve_fn(:typename) do
    142     fn
    143       _, %{parent_type: %Absinthe.Type.Object{} = type} ->
    144         {:ok, type.name}
    145 
    146       _, %{source: source, parent_type: %Absinthe.Type.Interface{} = iface} = env ->
    147         case Absinthe.Type.Interface.resolve_type(iface, source, env) do
    148           nil ->
    149             {:error, "Could not resolve type of concrete " <> iface.name}
    150 
    151           type ->
    152             {:ok, type.name}
    153         end
    154 
    155       _, %{source: source, parent_type: %Absinthe.Type.Union{} = union} = env ->
    156         case Absinthe.Type.Union.resolve_type(union, source, env) do
    157           nil ->
    158             {:error, "Could not resolve type of concrete " <> union.name}
    159 
    160           type ->
    161             {:ok, type.name}
    162         end
    163     end
    164   end
    165 
    166   def filter_fields(fields) do
    167     for {key, field = %{name: name}} <- fields, not String.starts_with?(name, "__"), into: %{} do
    168       {key, field}
    169     end
    170   end
    171 end