GreenFairy.Scalar (GreenFairy v0.3.0)
View SourceDefines a custom GraphQL scalar type with a clean DSL.
Usage
defmodule MyApp.GraphQL.Scalars.DateTime do
use GreenFairy.Scalar
scalar "DateTime" do
parse fn
%Absinthe.Blueprint.Input.String{value: value}, _ ->
case DateTime.from_iso8601(value) do
{:ok, datetime, _} -> {:ok, datetime}
_ -> :error
end
_, _ -> :error
end
serialize fn datetime ->
DateTime.to_iso8601(datetime)
end
end
endCQL Operators
Define custom operators for filtering on this scalar type. This example uses
the geo library from Hex (https://hex.pm/packages/geo):
defmodule MyApp.GraphQL.Scalars.Point do
use GreenFairy.Scalar
@moduledoc "GraphQL scalar for Geo.Point from the geo library"
scalar "Point" do
description "A geographic point (longitude, latitude)"
parse fn
%Absinthe.Blueprint.Input.Object{fields: fields}, _ ->
lng = get_field(fields, "lng") || get_field(fields, "longitude")
lat = get_field(fields, "lat") || get_field(fields, "latitude")
{:ok, %Geo.Point{coordinates: {lng, lat}, srid: 4326}}
_, _ ->
:error
end
serialize fn %Geo.Point{coordinates: {lng, lat}} ->
%{lng: lng, lat: lat}
end
# Define available operators for CQL
operators [:eq, :near, :within_distance]
# Define custom CQL input type (Hasura-style with underscores)
cql_input "CqlOpPointInput" do
field :_eq, :point
field :_near, :point_near_input
field :_within_distance, :point_distance_input
field :_is_null, :boolean
end
# PostGIS-compatible filter using ST_DWithin
filter :near, fn field, %Geo.Point{} = point, opts ->
distance_meters = opts[:distance] || 1000
{:fragment, "ST_DWithin(?::geography, ?::geography, ?)", field, point, distance_meters}
end
filter :within_distance, fn field, %{point: point, distance: distance} ->
{:fragment, "ST_DWithin(?::geography, ?::geography, ?)", field, point, distance}
end
end
defp get_field(fields, name) do
Enum.find_value(fields, fn %{name: n, input_value: %{value: v}} ->
if n == name, do: v
end)
end
endOptions
:description- Description of the scalar type (can also use @desc)
Summary
Functions
Defines a custom CQL operator input type for this scalar.
Defines how to apply a filter operator for this scalar type.
Defines the CQL operators available for this scalar type.
Defines a custom GraphQL scalar type.
Functions
Defines a custom CQL operator input type for this scalar.
This generates a CqlOp{Scalar}Input type with fields for each operator.
Example
scalar "Point" do
operators [:eq, :near, :within_distance]
cql_input "CqlOpPointInput" do
field :_eq, :point
field :_near, :point_near_input
field :_within_distance, :point_distance_input
end
endHasura-style Operators
By convention, CQL operators use underscore prefixes (_eq, _near, etc.) to match Hasura's filtering syntax.
Defines how to apply a filter operator for this scalar type.
Examples
# Simple filter
filter :near, fn field, value ->
{:geo_near, field, value}
end
# Filter with options
filter :within_radius, fn field, value, opts ->
radius = opts[:radius] || 10
{:geo_within, field, value, radius}
end
Defines the CQL operators available for this scalar type.
Example
scalar "Point" do
operators [:eq, :near, :within_distance]
# ...
end
Defines a custom GraphQL scalar type.
Examples
scalar "DateTime" do
parse fn input, _ ->
case DateTime.from_iso8601(input.value) do
{:ok, datetime, _} -> {:ok, datetime}
_ -> :error
end
end
serialize fn datetime ->
DateTime.to_iso8601(datetime)
end
end