Announcing GraphQLClient.jl, a GraphQL client which facilitates easy and Julian interaction with a GraphQL server.
Key features
- Type stable querying , mutating and subscribing without manual writing of query strings
- Deserializing responses directly into structs using StructTypes
- Construction of Julia types from GraphQL objects
- Using introspection to help with querying
For more information please see the basic usage below and the docs.
Status
This package has been in use internally for about a year and a half and we wanted to release it as we’ve found it very helpful, and hope you do to! This means that it has been used extensively with one server and whilst a lot of effort has been made to make it general and match the GraphQL specification, there may be some issues as it’s used more in the wild, plus there are some features that we’d still like to add. So please give it a go, let us know how you get on, check out the issues and get involved!
Basic Usage
Connecting to a server
A client can be instantiated by using the Client
type
using GraphQLClient
client = Client("https://countries.trevorblades.com")
This will, by default, use a query to introspect the server schema.
We can also set a global client to be user by queries, mutations, subscriptions and introspection functions.
global_graphql_client(Client("https://countries.trevorblades.com"))
Querying
We can query a client
without having to type a full GraphQL query by hand, with the response containing fields obtained by introspection
response = query(client, "countries")
Or we can query the global client
response = query("countries")
We can add arguments and specify fields in the response
query_args = Dict("filter" => Dict("code" => Dict("eq" => "AU")))
response = query("countries"; query_args=query_args, output_fields="name");
response.data["countries"]
# 1-element Vector{Any}:
# Dict{String, Any}("name" => "Australia")
Or we can query with the query string directly
query_string = """
query(
\$eq: String
){
countries(
filter:{
code:{
eq:\$eq
}
}
){
name
}
}
"""
variables = Dict("eq" => "AU")
response = GraphQLClient.execute(query_string, variables=variables)
We can define a StructType
to deserialise the result into
using StructTypes
StructTypes.@OrderedStruct struct CountryName
name::String
end
response = query("countries", Vector{CountryName}, query_args=query_args, output_fields="name")
response.data["countries"][1]
# CountryName("Australia")
Or we can use introspection to build the type automatically
Country = GraphQLClient.introspect_object("Country")
response = query("countries", Vector{Country}, query_args=query_args, output_fields="name")
response.data["countries"][1]
# Country
# name : Australia
Mutations
Mutations can be constructed in a similar way, except the arguments are not a keyword argument as typically a mutation is doing something with an input. For example
response = mutate(client, "mutation_name", Dict("new_id" => 1))
response = mutate("mutation_name", Dict("new_id" => 1)) # Use global client
Subscriptions
The subscriptions syntax is similar, except that we use Julia’s do
notation
open_subscription(
client,
"subscription_name",
sub_args=("id" => 1),
output_fields="val"
) do response
val = response.data["subscription_name"]["val"]
stop_sub = val == 2
return stop_sub # If this is true, the subscription ends
end
Acknowledgement
A huge thanks to Deloitte Australia for allowing this to be open sourced and encouraging open source contributions.