An elm/json
inspired package for working with GraphQL
elm install ryan-haskell/graphql
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:
GraphQL.Decode
- Decode JSON responses sent from a GraphQL APIGraphQL.Encode
- Create JSON values to send as variables to a GraphQL APIGraphQL.Http
- Send HTTP requests to a GraphQL API endpointGraphQL.Scalar.ID
- Work with the built-in GraphQLID
scalarGraphQL.Operation
- LikeGraphQL.Http
, but allows you to handleCmd
values in one placeGraphQL.Error
- Work with GraphQL validation errors
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 )
]
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
]
}
}
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:
- dillonkearns/elm-graphql – Write Elm code, generate GraphQL
- vendrinc/elm-gql – Write GraphQL, generate Elm code