zf

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

scalar_leafs.ex (2877B)


      1 # [sic]
      2 defmodule Absinthe.Phase.Document.Validation.ScalarLeafs do
      3   @moduledoc false
      4 
      5   # Validates that all leaf nodes are scalars.
      6   #
      7   # # Examples:
      8   # Assume `user` field is an object, and `email` is a scalar.
      9   #
     10   # ## DO NOT
     11   # ```
     12   # {
     13   #   user
     14   # }
     15   # ```
     16   #
     17   # ## DO
     18   # ```
     19   # {
     20   #   user {name email}
     21   # }
     22   # ```
     23   #
     24   # ## DO NOT
     25   # ```
     26   # {
     27   #   email { fields on scalar }
     28   # }
     29   # ```
     30   #
     31   # ## DO
     32   # ```
     33   # {
     34   #   email
     35   # }
     36   # ```
     37 
     38   alias Absinthe.{Blueprint, Phase, Type}
     39 
     40   use Absinthe.Phase
     41   use Absinthe.Phase.Validation
     42 
     43   @doc """
     44   Run the validation.
     45   """
     46   @spec run(Blueprint.t(), Keyword.t()) :: Phase.result_t()
     47   def run(input, _options \\ []) do
     48     result = Blueprint.prewalk(input, &handle_node(&1, input.schema))
     49     {:ok, result}
     50   end
     51 
     52   defp handle_node(%{schema_node: nil} = node, _schema), do: {:halt, node}
     53 
     54   defp handle_node(%Blueprint.Document.Field{schema_node: schema_node} = node, schema) do
     55     type = Type.expand(schema_node.type, schema)
     56     process(node, Type.unwrap(type), type)
     57   end
     58 
     59   defp handle_node(node, _) do
     60     node
     61   end
     62 
     63   @has_subfields [
     64     Type.Object,
     65     Type.Union,
     66     Type.Interface
     67   ]
     68 
     69   defp process(%{selections: []} = node, %unwrapped{}, type) when unwrapped in @has_subfields do
     70     bad_node(node, type, :missing_subfields)
     71   end
     72 
     73   defp process(%{selections: s} = node, %unwrapped{}, type)
     74        when s != [] and unwrapped not in @has_subfields do
     75     bad_node(node, type, :bad_subfields)
     76   end
     77 
     78   defp process(node, _, _) do
     79     node
     80   end
     81 
     82   defp bad_node(node, type, :bad_subfields = flag) do
     83     node
     84     |> flag_invalid(flag)
     85     |> put_error(error(node, no_subselection_allowed_message(node.name, Type.name(type))))
     86   end
     87 
     88   defp bad_node(node, type, :missing_subfields = flag) do
     89     node
     90     |> flag_invalid(flag)
     91     |> put_error(error(node, required_subselection_message(node.name, Type.name(type))))
     92   end
     93 
     94   # Generate the error
     95   @spec error(Blueprint.Document.Field.t(), String.t()) :: Phase.Error.t()
     96   defp error(node, message) do
     97     %Phase.Error{
     98       phase: __MODULE__,
     99       message: message,
    100       locations: [node.source_location]
    101     }
    102   end
    103 
    104   @doc """
    105   Generate the error message for an extraneous field subselection.
    106   """
    107   @spec no_subselection_allowed_message(String.t(), String.t()) :: String.t()
    108   def no_subselection_allowed_message(field_name, type_name) do
    109     ~s(Field "#{field_name}" must not have a selection since type "#{type_name}" has no subfields.)
    110   end
    111 
    112   @doc """
    113   Generate the error message for a missing field subselection.
    114   """
    115   @spec required_subselection_message(String.t(), String.t()) :: String.t()
    116   def required_subselection_message(field_name, type_name) do
    117     ~s(Field "#{field_name}" of type "#{type_name}" must have a selection of subfields. Did you mean "#{
    118       field_name
    119     } { ... }"?)
    120   end
    121 end