type_names_are_reserved.ex (2497B)
1 defmodule Absinthe.Phase.Schema.Validation.TypeNamesAreReserved do 2 @moduledoc false 3 4 use Absinthe.Phase 5 alias Absinthe.Blueprint 6 alias Absinthe.Blueprint.Schema 7 8 def run(bp, _) do 9 bp = Blueprint.prewalk(bp, &validate_reserved/1) 10 {:ok, bp} 11 end 12 13 def allow_reserved(node = %{flags: nil}) do 14 allow_reserved(%{node | flags: %{}}) 15 end 16 17 def allow_reserved(node = %{flags: flags}) do 18 flags = 19 flags 20 |> Map.put(:reserved_name, true) 21 22 %{node | flags: flags} 23 end 24 25 def make_reserved(node = %{name: "__" <> _}) do 26 allow_reserved(node) 27 end 28 29 def make_reserved(node = %{name: name, identifier: identifier}) do 30 node = %{ 31 node 32 | name: name |> String.replace_prefix("", "__"), 33 identifier: 34 identifier |> to_string() |> String.replace_prefix("", "__") |> String.to_atom() 35 } 36 37 allow_reserved(node) 38 end 39 40 defp validate_reserved(%struct{name: "__" <> _} = entity) do 41 reserved_ok = 42 Absinthe.Type.built_in_module?(entity.__reference__.module) || 43 reserved_name_ok_flag?(entity) 44 45 if reserved_ok do 46 entity 47 else 48 kind = struct_to_kind(struct) 49 50 detail = %{artifact: "#{kind} name", value: entity.name} 51 52 entity |> put_error(error(entity, detail)) 53 end 54 end 55 56 defp validate_reserved(entity) do 57 entity 58 end 59 60 defp reserved_name_ok_flag?(%{flags: flags}) do 61 flags[:reserved_name] 62 end 63 64 defp reserved_name_ok_flag?(_) do 65 false 66 end 67 68 defp error(object, data) do 69 %Absinthe.Phase.Error{ 70 message: explanation(data), 71 locations: [object.__reference__.location], 72 phase: __MODULE__, 73 extra: data 74 } 75 end 76 77 defp struct_to_kind(Schema.InputValueDefinition), do: "argument" 78 defp struct_to_kind(Schema.FieldDefinition), do: "field" 79 defp struct_to_kind(Schema.DirectiveDefinition), do: "directive" 80 defp struct_to_kind(_), do: "type" 81 82 @description """ 83 Type system artifacts must not begin with two leading underscores. 84 85 > GraphQL type system authors must not define any types, fields, arguments, 86 > or any other type system artifact with two leading underscores. 87 88 Reference: https://github.com/facebook/graphql/blob/master/spec/Section%204%20--%20Introspection.md#naming-conventions 89 90 """ 91 92 def explanation(%{artifact: artifact, value: value}) do 93 artifact_name = String.capitalize(artifact) 94 95 """ 96 #{artifact_name} #{inspect(value)} starts with two leading underscores. 97 98 #{@description} 99 """ 100 end 101 end