Announcing AbsintheClient - A GraphQL client designed for Absinthe.
What is AbsintheClient?
AbsintheClient is a Req plugin to perform GraphQL operations, including subscriptions.
- Performs
query
andmutation
operations via JSON POST requests. - Performs
subscription
operations over WebSockets (Absinthe Phoenix). - Automatically re-establishes subscriptions on socket disconnect/reconnect.
- Supports virtually all
Req.request/1
options, notably:
Here is an example straight from the docs using rickandmortyapi.com to fetch all the Cronenbergs:
req = Req.new(base_url: "https://rickandmortyapi.com") |> AbsintheClient.attach()
Req.post!(req,
graphql: {
"""
query ($name: String!) {
characters(filter: {name: $name}) {
results {
name
}
}
}
""",
%{name: "Cronenberg"}
}
).body["data"]
%{
"characters" => %{
"results" => [
%{"name" => "Cronenberg Rick"},
%{"name" => "Cronenberg Morty"}
]
}
}
Subscriptions
AbsintheClient includes a custom adapter for performing operations over WebSockets, which is mostly useful for managing subscriptions.
Speaking of subscriptions, one killer feature in AbsintheClient is the ability to automatically re-establish subscriptions on disconnect/reconnect. When your WebSocket disconnects, whether due to network failure, rolling deployment, or an elusive third thing, when the socket reconnects AbsintheClient will automatically re-subscribe to any active subscriptions.
Let’s review a subscriptions example. In this scenario an Absinthe server has defined a subscription for leaving comments on repositories. We can create a subscription to listen for new comments:
client = Req.new(base_url: "http://localhost:4000") |> AbsintheClient.attach()
websocket = AbsintheClient.WebSocket.connect!(client, url: "/subscriptions/websocket")
gql =
"""
subscription RepoCommentSubscription($repository: Repository!){
repoCommentSubscribe(repository: $repository){
id
commentary
}
}
"""
variables = %{"repository" => "absinthe-graphql/absinthe"}
Req.request!(client, web_socket: web_socket, graphql: {gql, variables}).body
#=> %AbsintheClient.Subscription{}
When a change occurs, the server will publish a message with the subscription data:
IEx.Helpers.flush()
#=> %AbsintheClient.WebSocket.Message{event: "subscription:data", payload: %{"data" => %{"repoCommentSubscribe" => %{"id" => 1, "commentary" => "Absinthe is great!"}}}
The Future
The initial release of AbsintheClient was just a necessary first step. We are embarking on an exciting new journey around GraphQL state management in Elixir, specifically in Phoenix LiveView. Over the next few weeks and months, expect to see more releases with tools for managing Absinthe socket state in the LiveView process, operation bindings with loading states, pagination, and much, much more!
For the GraphQL (not Absinthe) users– we are not leaving you out in the cold! Query and mutation operations work today for all GraphQL servers that support JSON POST requests. Support for other formats is planned. Subscriptions support is underway, too– we have made solid initial progress on a graphql-transport-ws
adapter, too. It won’t provide all of the same guarantees as the Phoenix Channels implementation, but it will definitely support automatic re-subscription so stay tuned for those updates.
Getting involved
First and foremost, if you’re an Absinthe user we would love to get your feedback– do you see a use case for AbsintheClient? What kind of tools would you like to see in a client library? What should we focus on next?
Finally if you are remotely interested in improving the state of GraphQL client operations in Elixir, we would love to have your help! Several members of the CargoSense team have tackled this problem from different angles at different times and we would like to begin coordinating this effort around the AbsintheClient library.
Thanks for reading and happy gardening!