Crate artemis[−][src]
A modern GraphQL Client with common built-in features as well as the ability to extend its functionality through exchanges
Getting Started
The first step is to write some queries in .graphql
files and then add the following to your
build.rs
(create it if necessary):
use artemis_build::CodegenBuilder; fn main() { CodegenBuilder::new() .introspect_schema("http://localhost:8080/graphql", None, Vec::new()) .unwrap() .add_query("queries/x.graphql") .with_out_dir("src/queries") .build() .unwrap(); }
Afterwards, you can use the crate in your application as such:
use artemis::Client; use artemis_test::get_conference::{GetConference, get_conference::Variables}; let client = Client::builder("http://localhost:8080/graphql") .with_default_exchanges() .build(); let result = client.query(GetConference, Variables { id: "1".to_string() }).await.unwrap(); assert!(result.data.is_some());
For more info see the relevant method and struct documentation.
Build
This crate uses code generation to take your GraphQL files and turn them into
strongly typed Rust modules. These contain the query struct, a zero-size type
such as GetConference
, as well as a submodule containing the Variables
,
any input types, the ResponseData
type and any involved output types.
Having a strongly typed compile time representation with additional info
(such as the __typename
of all involved types and an abstract selection tree)
means that the work the CPU has to do at runtime is very minimal,
only amounting to serialization, deserialization and simple lookups using
the statically generated data.
For details on how to use the query builder, see artemis-build
Exchanges
Exchanges are like a bi-directional middleware. They act on both the incoming and outgoing queries, passing them on if they can’t return a result themselves.
There are three default exchanges, called in this order:
DedupExchange
The deduplication exchange (DedupExchange
) filters out unnecessary queries
by combining multiple identical queries into one. It does so by keeping track
of in-flight queries and, instead of firing off another identical query,
waiting for their results instead. This reduces network traffic,
especially in larger applications where the same query may be used in multiple
places and run multiple times simultaneously as a result.
CacheExchange
The cache exchange is a very basic, un-normalized cache which eagerly invalidates queries.
It’s focused on simplicity and correctness of data, so if a query uses any of the same types
as a mutation it will always be invalidated by it. This means that especially if you
have large amounts of different entities of the same type, this can become expensive quickly.
For a more advanced normalized cache that invalidates only directly related entities
see the artemis-normalized-cache
crate.
FetchExchange
The fetch exchange will serialize the query, send it over the network and deserialize the response.
This works on x86 using reqwest
, or fetch
if you’re using WASM.
This should be your last exchange in the chain, as it never forwards a query.
WASM
WASM support requires some minor boilerplate in your code.
First, there’s a wasm
module in your queries. this contains an automatically generated enum
containing all your queries. This is used for transmitting type data across the WASM
boundary.
Second, you have to use the wasm_client! macro to generate a WASM interop client that has hard-coded types for your queries, again, to eliminate the unsupported generics and transmit type data across the boundary. The queries type passed to the macro must be the enum generated as mentioned above.
Documentation of the JavaScript types and methods can be found in the TypeScript definitions that are output when you build your WASM.
Features
default-exchanges
(default) - Include default exchanges and the related builder methodobservable
(default) - Include support for observable and all related types. Includestokio
on x86.
Re-exports
pub use client::Client; |
Modules
client | Contains client-related types. |
codegen | Types used only by the code generator. Exchanges may use these, but they shouldn’t be created/implemented manually. |
default_exchanges | This module contains the default exchanges.
Note that these require the |
exchange | Types used by custom exchanges. Regular users probably don’t need these. |
utils | Contains utility functions mainly used internally, but they’re public for use in exchanges and macros. |
Macros
ext | Creates a new |
wasm_client | Generate a WASM client wrapper that gets exported in your WASM binary This is required because WASM doesn’t support generics and the regular Client uses a lot of them. It will hard-code your exchanges, as well as other options you may pass to the macro. |
Structs
ClientBuilder | A builder for the artemis client. |
DebugInfo | Debug info used for… well, debugging. |
Error | An element in the top-level |
ExtensionMap | A map of keyed extensions. The key is only used for JS interop, the Rust version uses the type as the key. |
HeaderPair | A key-value pair used for custom headers. |
Location | Represents a location inside a query string. Used in errors. See Error. |
Observable | An observable result. This implements |
QueryBody | The form in which queries are sent over HTTP in most implementations. This will be built using the GraphQLQuery trait normally. |
QueryError | A query error wrapper that allows for cheap and easy cloning across threads.
If a |
QueryOptions | Options that can be passed to a query.
This will be combined with |
Response | The generic shape taken by the responses of GraphQL APIs. |
Enums
PathFragment | Part of a path in a query. It can be an object key or an array index. See Error. |
RequestPolicy | The request policy of the request. |
ResultSource | The source of the result (cache or network). Used for debugging. |
Traits
GraphQLQuery | A convenience trait that can be used to build a GraphQL request body. This will be implemented for you by codegen. It is implemented on the struct you place the derive on. |
Type Definitions
Extensions | A thread-safe wrapper around ExtensionMap. |