scalars.ex (4551B)
1 defmodule Absinthe.Type.BuiltIns.Scalars do 2 use Absinthe.Schema.Notation 3 4 @moduledoc false 5 6 scalar :integer, name: "Int" do 7 description """ 8 The `Int` scalar type represents non-fractional signed whole numeric values. 9 Int can represent values between `-(2^53 - 1)` and `2^53 - 1` since it is 10 represented in JSON as double-precision floating point numbers specified 11 by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). 12 """ 13 14 serialize &__MODULE__.serialize_integer/1 15 parse parse_with([Absinthe.Blueprint.Input.Integer], &parse_int/1) 16 end 17 18 def serialize_integer(n) when is_integer(n), do: n 19 20 def serialize_integer(n) do 21 raise Absinthe.SerializationError, """ 22 Value #{inspect(n)} is not a valid integer 23 """ 24 end 25 26 scalar :float do 27 description """ 28 The `Float` scalar type represents signed double-precision fractional 29 values as specified by 30 [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). 31 """ 32 33 serialize &__MODULE__.serialize_float/1 34 35 parse parse_with( 36 [Absinthe.Blueprint.Input.Integer, Absinthe.Blueprint.Input.Float], 37 &parse_float/1 38 ) 39 end 40 41 def serialize_float(n) when is_float(n), do: n 42 def serialize_float(n) when is_integer(n), do: n * 1.0 43 44 def serialize_float(n) do 45 raise Absinthe.SerializationError, """ 46 Value #{inspect(n)} is not a valid float 47 """ 48 end 49 50 scalar :string do 51 description """ 52 The `String` scalar type represents textual data, represented as UTF-8 53 character sequences. The String type is most often used by GraphQL to 54 represent free-form human-readable text. 55 """ 56 57 serialize &String.Chars.to_string/1 58 parse parse_with([Absinthe.Blueprint.Input.String], &parse_string/1) 59 end 60 61 scalar :id, name: "ID" do 62 description """ 63 The `ID` scalar type represents a unique identifier, often used to 64 refetch an object or as key for a cache. The ID type appears in a JSON 65 response as a String; however, it is not intended to be human-readable. 66 When expected as an input type, any string (such as `"4"`) or integer 67 (such as `4`) input value will be accepted as an ID. 68 """ 69 70 serialize &to_string/1 71 72 parse parse_with( 73 [Absinthe.Blueprint.Input.Integer, Absinthe.Blueprint.Input.String], 74 &parse_id/1 75 ) 76 end 77 78 scalar :boolean do 79 description """ 80 The `Boolean` scalar type represents `true` or `false`. 81 """ 82 83 serialize &__MODULE__.serialize_boolean/1 84 parse parse_with([Absinthe.Blueprint.Input.Boolean], &parse_boolean/1) 85 end 86 87 def serialize_boolean(true), do: true 88 def serialize_boolean(false), do: false 89 90 def serialize_boolean(val) do 91 raise Absinthe.SerializationError, """ 92 Value #{inspect(val)} is not a valid boolean 93 """ 94 end 95 96 # Integers are only safe when between -(2^53 - 1) and 2^53 - 1 due to being 97 # encoded in JavaScript and represented in JSON as double-precision floating 98 # point numbers, as specified by IEEE 754. 99 @max_int 9_007_199_254_740_991 100 @min_int -9_007_199_254_740_991 101 102 @spec parse_int(any) :: {:ok, integer} | :error 103 defp parse_int(value) when is_integer(value) and value >= @min_int and value <= @max_int do 104 {:ok, value} 105 end 106 107 defp parse_int(_) do 108 :error 109 end 110 111 @spec parse_float(any) :: {:ok, float} | :error 112 defp parse_float(value) when is_float(value) do 113 {:ok, value} 114 end 115 116 defp parse_float(value) when is_integer(value) do 117 {:ok, value * 1.0} 118 end 119 120 defp parse_float(_) do 121 :error 122 end 123 124 @spec parse_string(any) :: {:ok, binary} | :error 125 defp parse_string(value) when is_binary(value) do 126 {:ok, value} 127 end 128 129 defp parse_string(_) do 130 :error 131 end 132 133 @spec parse_id(any) :: {:ok, binary} | :error 134 defp parse_id(value) when is_binary(value) do 135 {:ok, value} 136 end 137 138 defp parse_id(value) when is_integer(value) do 139 {:ok, Integer.to_string(value)} 140 end 141 142 defp parse_id(_) do 143 :error 144 end 145 146 @spec parse_boolean(any) :: {:ok, boolean} | :error 147 defp parse_boolean(value) when is_boolean(value) do 148 {:ok, value} 149 end 150 151 defp parse_boolean(_) do 152 :error 153 end 154 155 # Parse, supporting pulling values out of blueprint Input nodes 156 defp parse_with(node_types, coercion) do 157 fn 158 %{__struct__: str, value: value} -> 159 if Enum.member?(node_types, str) do 160 coercion.(value) 161 else 162 :error 163 end 164 165 %Absinthe.Blueprint.Input.Null{} -> 166 {:ok, nil} 167 168 other -> 169 coercion.(other) 170 end 171 end 172 end