unique_operation_names.ex (1751B)
1 defmodule Absinthe.Phase.Document.Validation.UniqueOperationNames do 2 @moduledoc false 3 4 # Validates document to ensure that all operations have unique names. 5 6 alias Absinthe.{Blueprint, Phase} 7 8 use Absinthe.Phase 9 use Absinthe.Phase.Validation 10 11 @doc """ 12 Run the validation. 13 """ 14 @spec run(Blueprint.t(), Keyword.t()) :: Phase.result_t() 15 def run(input, _options \\ []) do 16 operations = 17 for operation <- input.operations do 18 process(operation, input.operations) 19 end 20 21 result = %{input | operations: operations} 22 {:ok, result} 23 end 24 25 @spec process(Blueprint.Document.Operation.t(), [Blueprint.Document.Operation.t()]) :: 26 Blueprint.Document.Operation.t() 27 defp process(%{name: nil} = operation, _) do 28 operation 29 end 30 31 defp process(operation, operations) do 32 if duplicate?(operations, operation) do 33 operation 34 |> flag_invalid(:duplicate_name) 35 |> put_error(error(operation)) 36 else 37 operation 38 end 39 end 40 41 # Whether a duplicate operation is present 42 @spec duplicate?([Blueprint.Document.Operation.t()], Blueprint.Document.Operation.t()) :: 43 boolean 44 defp duplicate?(operations, operation) do 45 Enum.count(operations, &(&1.name == operation.name)) > 1 46 end 47 48 # Generate an error for a duplicate operation. 49 @spec error(Blueprint.Document.Operation.t()) :: Phase.Error.t() 50 defp error(node) do 51 %Phase.Error{ 52 phase: __MODULE__, 53 message: error_message(node.name), 54 locations: [node.source_location] 55 } 56 end 57 58 @doc """ 59 Generate an error message for a duplicate operation. 60 """ 61 @spec error_message(String.t()) :: String.t() 62 def error_message(name) do 63 ~s(There can only be one operation named "#{name}".) 64 end 65 end