Packages
absinthe
0.4.3
1.11.0
1.10.2
1.10.1
1.10.0
1.9.1
1.9.0
1.8.0
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.8
1.6.7
retired
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.6.0-rc.1
1.6.0-rc.0
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.5.0-rc.5
1.5.0-rc.4
1.5.0-rc.3
1.5.0-rc.2
1.5.0-rc.1
1.5.0-rc.0
1.5.0-beta.2
1.5.0-beta.1
1.5.0-beta.0
1.5.0-alpha.4
1.5.0-alpha.3
1.5.0-alpha.2
1.5.0-alpha.1
1.5.0-alpha.0
1.4.16
1.4.15
1.4.14
1.4.13
1.4.12
1.4.11
1.4.10
1.4.9
1.4.8
retired
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.4.0-rc.3
1.4.0-rc.2
1.4.0-rc.1
1.4.0-rc.0
1.4.0-beta.5
1.4.0-beta.4
1.4.0-beta.3
1.4.0-beta.2
1.4.0-beta.1
1.3.2
1.3.1
1.3.0
1.3.0-rc.0
1.3.0-beta.2
1.3.0-beta.1
1.3.0-beta.0
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.2.0-rc.0
1.2.0-beta.0
1.2.0-alpha0
1.2.0-alpha.2
1.2.0-alpha.1
1.1.11
1.1.10
1.1.9
1.1.8
1.1.7
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.0
0.5.2
0.5.1
0.5.0
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.2.3
0.2.2
0.2.1
0.1.0
GraphQL for Elixir
Current section
Files
Jump to
Current section
Files
lib/absinthe/type/scalar.ex
defmodule Absinthe.Type.Scalar do
@moduledoc """
Represents a primitive value.
GraphQL responses take the form of a hierarchical tree; the leaves on these
trees are scalars.
Also see `Absinthe.Type.Object`.
## Built-In Scalars
The following built-in scalar types are defined:
* `:boolean` - Represents `true` or `false`. See the [GraphQL Specification](https://facebook.github.io/graphql/#sec-Boolean).
* `:float` - Represents signed double‐precision fractional values as specified by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). See the [GraphQL Specification](https://facebook.github.io/graphql/#sec-Float).
* `:id` - Represents a unique identifier, often used to refetch an object or as key for a cache. The ID type is serialized in the same way as a String; however, it is not intended to be human‐readable. See the [GraphQL Specification](https://facebook.github.io/graphql/#sec-ID).
* `:integer` - Represents a signed 32‐bit numeric non‐fractional value, greater than or equal to -2^31 and less than 2^31. Note that Absinthe uses the full word `:integer` to identify this type, but its `name` (used by variables, for instance), is `"Int"`. See the [GraphQL Specification](https://facebook.github.io/graphql/#sec-Int).
* `:string` - Represents textual data, represented as UTF‐8 character sequences. The String type is most often used by GraphQL to represent free‐form human‐readable text. See the [GraphQL Specification](https://facebook.github.io/graphql/#sec-String).
## Examples
Supporting a time format in ISOz format, using [Timex](http://hexdocs.pm/timex):
```
use Absinthe.Field.Definitions
# Also loaded by `use Absinthe.Field.Schema`
@absinthe :type
def time do
%Absinthe.Type.Scalar{
description: "Time (in ISOz format)",
parse: &Timex.DateFormat.parse(&1, "{ISOz}"),
serialize: &Timex.DateFormat.format!(&1, "{ISOz}")
}
end
```
"""
use Absinthe.Introspection.Kind
use Absinthe.Type.Definitions
alias __MODULE__
alias Absinthe.Flag
alias Absinthe.Type
@typedoc """
A defined scalar type.
Note new scalars should be defined using `@absinthe :type` from `Absinthe.Type.Definitions`.
* `:name` - The name of scalar. Should be a TitleCased `binary`. Set automatically when using `@absinthe :type` from `Absinthe.Type.Definitions`.
* `:description` - A nice description for introspection.
* `:serialize` - A function used to convert a value to a form suitable for JSON serialization
* `:parse` - A function used to convert the raw, incoming form of a scalar to the canonical internal format.
The `:reference` key is for internal use.
"""
@type t :: %{name: binary, description: binary, serialize: (value_t -> any), parse: (any -> {:ok, value_t} | :error), reference: Type.Reference.t}
@typedoc "The internal, canonical representation of a scalar value"
@type value_t :: any
defstruct name: nil, description: nil, serialize: nil, parse: nil, reference: nil
@absinthe :type
@doc false
@spec integer :: t
def integer do
%Scalar{name: "Int",
description: """
The `Int` scalar type represents non-fractional signed whole numeric
values. Int can represent values between -(2^53 - 1) and 2^53 - 1 since
represented in JSON as double-precision floating point numbers specified
by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point).
""" |> String.replace("\n", " "),
serialize: &(&1),
parse: parse_with([Absinthe.Language.IntValue], &parse_int/1)}
end
@absinthe :type
@doc false
@spec float :: t
def float do
%Scalar{name: "Float",
description: """
The `Float` scalar type represents signed double-precision fractional
values as specified by
[IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point).
""" |> String.replace("\n", " "),
serialize: &(&1),
parse: parse_with([Absinthe.Language.IntValue,
Absinthe.Language.FloatValue], &parse_float/1)}
end
@absinthe :type
@doc false
@spec string :: t
def string do
%Scalar{name: "String",
description: """
The `String` scalar type represents textual data, represented as UTF-8
character sequences. The String type is most often used by GraphQL to
represent free-form human-readable text.
""" |> String.replace("\n", " "),
serialize: &to_string/1,
parse: parse_with([Absinthe.Language.StringValue], &parse_string/1)}
end
@absinthe :type
@graphql_spec "https://facebook.github.io/graphql/#sec-ID"
@spec id :: t
def id do
%Scalar{name: "ID",
description: """
The `ID` scalar type represents a unique identifier, often used to
refetch an object or as key for a cache. The ID type appears in a JSON
response as a String; however, it is not intended to be human-readable.
When expected as an input type, any string (such as `"4"`) or integer
(such as `4`) input value will be accepted as an ID.
""" |> String.replace("\n", " "),
serialize: &to_string/1,
parse: parse_with([Absinthe.Language.IntValue,
Absinthe.Language.StringValue], &parse_string/1)}
end
@absinthe :type
@graphql_spec "https://facebook.github.io/graphql/#sec-Boolean"
@spec boolean :: t
def boolean do
%Scalar{name: "Boolean",
description: """
The `Boolean` scalar type represents `true` or `false`.
""" |> String.replace("\n", " "),
serialize: &(&1),
parse: parse_with([Absinthe.Language.BooleanValue],
&parse_boolean/1)}
end
# Integers are only safe when between -(2^53 - 1) and 2^53 - 1 due to being
# encoded in JavaScript and represented in JSON as double-precision floating
# point numbers, as specified by IEEE 754.
@max_int 9007199254740991
@min_int -9007199254740991
@spec parse_int(integer | float | binary) :: {:ok, integer} | :error
defp parse_int(value) when is_integer(value) do
cond do
value > @max_int -> @max_int
value < @min_int -> @min_int
true -> value
end
|> Flag.as(:ok)
end
defp parse_int(value) when is_float(value) do
with {result, _} <- Integer.parse(String.to_integer(value, 10)) do
parse_int(result)
end
end
defp parse_int(value) when is_binary(value) do
with {result, _} <- Integer.parse(value) do
parse_int(result)
end
end
@spec parse_float(integer | float | binary) :: {:ok, float} | :error
defp parse_float(value) when is_integer(value) do
{:ok, value * 1.0}
end
defp parse_float(value) when is_float(value) do
{:ok, value}
end
defp parse_float(value) when is_binary(value) do
with {value, _} <- Float.parse(value), do: {:ok, value}
end
defp parse_float(_value) do
:error
end
@spec parse_string(any) :: {:ok, binary} | :error
defp parse_string(value) do
try do
{:ok, to_string(value)}
rescue
Protocol.UndefinedError -> :error
end
end
@spec parse_boolean(any) :: {:ok, boolean} | :error
defp parse_boolean(value) when is_number(value) do
{:ok, value > 0}
end
defp parse_boolean(value) do
{:ok, !!value}
end
# Parse, supporting pulling values out of AST nodes
@spec parse_with([atom], (any -> value_t)) :: (any -> {:ok, value_t} | :error)
defp parse_with(node_types, coercion) do
fn
%{value: value} = node ->
if Enum.is_member?(node_types, node) do
coercion.(value)
else
nil
end
other ->
coercion.(other)
end
end
end