zf

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

result.ex (3996B)


      1 defmodule Absinthe.Phase.Document.Result do
      2   @moduledoc false
      3 
      4   # Produces data fit for external encoding from annotated value tree
      5 
      6   alias Absinthe.{Blueprint, Phase, Type}
      7   use Absinthe.Phase
      8 
      9   @spec run(Blueprint.t() | Phase.Error.t(), Keyword.t()) :: {:ok, map}
     10   def run(%Blueprint{} = bp, _options \\ []) do
     11     result = Map.merge(bp.result, process(bp))
     12     {:ok, %{bp | result: result}}
     13   end
     14 
     15   defp process(blueprint) do
     16     result =
     17       case blueprint.execution do
     18         %{validation_errors: [], result: nil} ->
     19           {:ok, data(%{value: nil}, [])}
     20 
     21         %{validation_errors: [], result: result} ->
     22           {:ok, data(result, [])}
     23 
     24         %{validation_errors: errors} ->
     25           {:validation_failed, errors}
     26       end
     27 
     28     format_result(result)
     29   end
     30 
     31   defp format_result({:ok, {data, []}}) do
     32     %{data: data}
     33   end
     34 
     35   defp format_result({:ok, {data, errors}}) do
     36     errors = errors |> Enum.uniq() |> Enum.map(&format_error/1)
     37     %{data: data, errors: errors}
     38   end
     39 
     40   defp format_result({:validation_failed, errors}) do
     41     errors = errors |> Enum.uniq() |> Enum.map(&format_error/1)
     42     %{errors: errors}
     43   end
     44 
     45   defp data(%{errors: [_ | _] = field_errors}, errors), do: {nil, field_errors ++ errors}
     46 
     47   # Leaf
     48   defp data(%{value: nil}, errors), do: {nil, errors}
     49 
     50   defp data(%{value: value, emitter: emitter}, errors) do
     51     value =
     52       case Type.unwrap(emitter.schema_node.type) do
     53         %Type.Scalar{} = schema_node ->
     54           try do
     55             Type.Scalar.serialize(schema_node, value)
     56           rescue
     57             _e in [Absinthe.SerializationError, Protocol.UndefinedError] ->
     58               raise(
     59                 Absinthe.SerializationError,
     60                 """
     61                 Could not serialize term #{inspect(value)} as type #{schema_node.name}
     62 
     63                 When serializing the field:
     64                 #{emitter.parent_type.name}.#{emitter.schema_node.name} (#{
     65                   emitter.schema_node.__reference__.location.file
     66                 }:#{emitter.schema_node.__reference__.location.line})
     67                 """
     68               )
     69           end
     70 
     71         %Type.Enum{} = schema_node ->
     72           Type.Enum.serialize(schema_node, value)
     73       end
     74 
     75     {value, errors}
     76   end
     77 
     78   # Object
     79   defp data(%{fields: fields}, errors), do: field_data(fields, errors)
     80 
     81   # List
     82   defp data(%{values: values}, errors), do: list_data(values, errors)
     83 
     84   defp list_data(fields, errors, acc \\ [])
     85   defp list_data([], errors, acc), do: {:lists.reverse(acc), errors}
     86 
     87   defp list_data([%{errors: errs} = field | fields], errors, acc) do
     88     {value, errors} = data(field, errors)
     89     list_data(fields, errs ++ errors, [value | acc])
     90   end
     91 
     92   defp field_data(fields, errors, acc \\ [])
     93   defp field_data([], errors, acc), do: {Map.new(acc), errors}
     94 
     95   defp field_data([%Absinthe.Resolution{} = res | _], _errors, _acc) do
     96     raise """
     97     Found unresolved resolution struct!
     98 
     99     You probably forgot to run the resolution phase again.
    100 
    101     #{inspect(res)}
    102     """
    103   end
    104 
    105   defp field_data([field | fields], errors, acc) do
    106     {value, errors} = data(field, errors)
    107     field_data(fields, errors, [{field_name(field.emitter), value} | acc])
    108   end
    109 
    110   defp field_name(%{alias: nil, name: name}), do: name
    111   defp field_name(%{alias: name}), do: name
    112   defp field_name(%{name: name}), do: name
    113 
    114   defp format_error(%Phase.Error{locations: []} = error) do
    115     error_object = %{message: error.message}
    116     Map.merge(error.extra, error_object)
    117   end
    118 
    119   defp format_error(%Phase.Error{} = error) do
    120     error_object = %{
    121       message: error.message,
    122       locations: Enum.flat_map(error.locations, &format_location/1)
    123     }
    124 
    125     error_object =
    126       case error.path do
    127         [] -> error_object
    128         path -> Map.put(error_object, :path, path)
    129       end
    130 
    131     Map.merge(Map.new(error.extra), error_object)
    132   end
    133 
    134   defp format_location(%{line: line, column: col}) do
    135     [%{line: line || 0, column: col || 0}]
    136   end
    137 
    138   defp format_location(_), do: []
    139 end