Skip to content

Instantly share code, notes, and snippets.

@jamesmacaulay
Created October 19, 2016 02:53
Show Gist options
  • Select an option

  • Save jamesmacaulay/d9390050931e7b857fa3a4f0fc6f034d to your computer and use it in GitHub Desktop.

Select an option

Save jamesmacaulay/d9390050931e7b857fa3a4f0fc6f034d to your computer and use it in GitHub Desktop.

Revisions

  1. jamesmacaulay created this gist Oct 19, 2016.
    160 changes: 160 additions & 0 deletions Query.elm
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,160 @@
    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