Skip to content

Instantly share code, notes, and snippets.

@jamesmacaulay
Created October 19, 2016 02:53
Show Gist options
  • Save jamesmacaulay/d9390050931e7b857fa3a4f0fc6f034d to your computer and use it in GitHub Desktop.
Save jamesmacaulay/d9390050931e7b857fa3a4f0fc6f034d to your computer and use it in GitHub Desktop.
module GraphQL.Query exposing (..)
import Json.Decode as Decode exposing (Decoder, (:=))
import Array exposing (Array)
type SelectionSet
= SelectionSet (List Selection)
type Selection
= FieldSelection Field
type Field
= Field
{ name : String
, selectionSet : SelectionSet
}
type Decodable a result
= Decodable a (Decoder result)
getAst : Decodable a result -> a
getAst (Decodable ast _) =
ast
getDecoder : Decodable a result -> Decoder result
getDecoder (Decodable _ decoder) =
decoder
string : Decodable SelectionSet String
string =
Decodable (SelectionSet []) Decode.string
int : Decodable SelectionSet Int
int =
Decodable (SelectionSet []) Decode.int
float : Decodable SelectionSet Float
float =
Decodable (SelectionSet []) Decode.float
bool : Decodable SelectionSet Bool
bool =
Decodable (SelectionSet []) Decode.bool
list : Decodable SelectionSet a -> Decodable SelectionSet (List a)
list (Decodable selectionSet decoder) =
Decodable selectionSet (Decode.list decoder)
array : Decodable SelectionSet a -> Decodable SelectionSet (Array a)
array (Decodable selectionSet decoder) =
Decodable selectionSet (Decode.array decoder)
object : (a -> b) -> Decodable SelectionSet (a -> b)
object constructor =
Decodable (SelectionSet []) (Decode.succeed constructor)
field :
String
-> Decodable SelectionSet a
-> Decodable SelectionSet (a -> b)
-> Decodable SelectionSet b
field name child parent =
let
field =
Field
{ name = name
, selectionSet = (getAst child)
}
(SelectionSet parentSelections) =
(getAst parent)
selections =
(FieldSelection field) :: parentSelections
decoder =
Decode.object2 (<|) (getDecoder parent) (getDecoder child)
in
Decodable (SelectionSet selections) decoder
type alias Project =
{ name : String }
type alias User =
{ name : String
, projects : Connection Project
}
type alias Connection a =
{ edges : List (Edge a)
, pageInfo : PageInfo
}
type alias Edge a =
{ cursor : String
, node : a
}
type alias PageInfo =
{ hasNextPage : Bool
, hasPreviousPage : Bool
}
edge child =
object Edge
|> field "cursor" string
|> field "node" child
pageInfo =
object PageInfo
|> field "hasNextPage" bool
|> field "hasPreviousPage" bool
connection child =
object Connection
|> field "edges" (list (edge child))
|> field "pageInfo" pageInfo
connectionField :
String
-> Decodable SelectionSet a
-> Decodable SelectionSet (Connection a -> b)
-> Decodable SelectionSet b
connectionField name child =
field name (connection child)
user : Decodable SelectionSet User
user =
let
project =
object Project
|> field "name" string
in
object User
|> field "name" string
|> connectionField "projects" project
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment