Skip to content

ryan-haskell/graphql

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@ryan-haskell/graphql

An elm/json inspired package for working with GraphQL

Installation

elm install ryan-haskell/graphql

Introduction

When working with JSON data, folks in the Elm community use the elm/json package. This is a great, general purpose library for safely handling unknown JSON sent from a backend API server.

This package builds on top of elm/json, adding functions designed specifically for working with GraphQL. This means you can easily work with scalars, enums, object types, input types, interfaces, and union types within your Elm application.

Here's a quick overview of what each module does:

  1. GraphQL.Decode - Decode JSON responses sent from a GraphQL API
  2. GraphQL.Encode - Create JSON values to send as variables to a GraphQL API
  3. GraphQL.Http - Send HTTP requests to a GraphQL API endpoint
  4. GraphQL.Scalar.ID - Work with the built-in GraphQL ID scalar
  5. GraphQL.Operation - Like GraphQL.Http, but allows you to handle Cmd values in one place
  6. GraphQL.Error - Work with GraphQL validation errors

A quick example

In the official GraphQL documentation, they begin their guide with a sample query that uses the Star Wars GraphQL API.

This is an example that shows how to use this package to create an HTTP request for use in your Elm application:

import GraphQL.Decode exposing (Decoder)
import GraphQL.Encode
import GraphQL.Http


type Msg
    = ApiResponded (Result GraphQL.Http.Error Data)



-- Sending a GraphQL query


findHero : String -> Cmd Msg
findHero heroId =
    GraphQL.Http.get
        { url = "/graphql"
        , query = """
            query FindHero($id: ID!) {
              hero(id: $id) {
                name
                appearsIn
              }
            }
          """
        , variables =
            [ ( "id", GraphQL.Encode.string heroId )
            ]
        , onResponse = ApiResponded
        , decoder = decoder
        }



-- Defining a GraphQL Decoder


type alias Data =
    { hero : Maybe Hero
    }


decoder : Decoder Data
decoder =
    GraphQL.Decode.object Data
        |> GraphQL.Decode.field
            { name = "hero"
            , decoder = GraphQL.Decode.maybe heroDecoder
            }


type alias Hero =
    { name : String
    , appearsIn : List Episode
    }


heroDecoder : Decoder Hero
heroDecoder =
    GraphQL.Decode.object Hero
        |> GraphQL.Decode.field
            { name = "name"
            , decoder = GraphQL.Decode.string
            }
        |> GraphQL.Decode.field
            { name = "appearsIn"
            , decoder = GraphQL.Decode.list episodeDecoder
            }


type Episode
    = NewHope
    | EmpireStrikesBack
    | ReturnOfTheJedi


episodeDecoder : Decoder Episode
episodeDecoder =
    GraphQL.Decode.enum
        [ ( "NEWHOPE", NewHope )
        , ( "EMPIRE", EmpireStrikesBack )
        , ( "JEDI", ReturnOfTheJedi )
        ]

Understanding how it works

When you send this HTTP request, using a function like GraphQL.Http.post, the GraphQL API server will receive the following request:

// POST /graphql

{
    "query": "query FindHero($id: Id!) { ... }",
    "variables": {
        "id": "1"
    }
}

When the API responds with a JSON payload, your decoder will convert the raw JSON into Elm values you can use in your application:

// The JSON sent from the API:
{
  "data": {
    "hero": {
      "name": "R2-D2",
      "appearsIn": [
        "NEWHOPE",
        "EMPIRE",
        "JEDI"
      ]
    }
  }
}
-- The JSON decoded into an Elm value
data ==
    { hero =
        Just
            { name = "R2-D2"
            , appearsIn =
                [ NewHope
                , EmpireStrikesBack
                , ReturnOfTheJedi
                ]
            }
    }

Comparison with other tools

This Elm package is for making GraphQL requests without any code generation or build tools.

If you'd like to use code generation to keep your backend GraphQL schema in-sync with your Elm application, there are some great tools that include an NPM CLI to generate that code for you:

  1. dillonkearns/elm-graphql – Write Elm code, generate GraphQL
  2. vendrinc/elm-gql – Write GraphQL, generate Elm code