2016-09-11 11:41:29 -05:00
|
|
|
# Juniper
|
|
|
|
|
|
|
|
> GraphQL server library for Rust
|
|
|
|
|
2016-10-09 09:55:18 -05:00
|
|
|
[![Build Status](https://travis-ci.org/mhallin/juniper.svg?branch=master)](https://travis-ci.org/mhallin/juniper)
|
|
|
|
[![Crates.io](https://img.shields.io/crates/v/juniper.svg?maxAge=2592000)](https://crates.io/crates/juniper)
|
2016-09-11 11:48:53 -05:00
|
|
|
|
2016-09-11 11:41:29 -05:00
|
|
|
---
|
|
|
|
|
|
|
|
[GraphQL][graphql] is a data query language developed by Facebook intended to
|
|
|
|
serve mobile and web application frontends. Juniper makes it possible to write
|
|
|
|
GraphQL servers in Rust that are type-safe and blazingly fast.
|
|
|
|
|
|
|
|
Juniper does not include a web server - instead it provides building blocks to
|
|
|
|
make integration with existing servers straightforward. It optionally provides a
|
|
|
|
pre-built integration for the [Iron framework][iron].
|
|
|
|
|
2016-12-05 10:06:09 -06:00
|
|
|
* [Cargo crate](https://crates.io/crates/juniper)
|
2016-12-18 12:52:14 -06:00
|
|
|
* [API Documentation](http://mhallin.github.io/juniper)
|
2016-12-05 10:06:09 -06:00
|
|
|
|
2016-09-11 11:41:29 -05:00
|
|
|
## Installation
|
|
|
|
|
|
|
|
Add Juniper to your Cargo.toml:
|
|
|
|
|
|
|
|
```toml
|
|
|
|
[dependencies]
|
2016-12-05 15:23:00 -06:00
|
|
|
juniper = "0.5.3"
|
2016-09-11 11:41:29 -05:00
|
|
|
```
|
|
|
|
|
|
|
|
If you want the Iron integration enabled, you need to enable the `iron-handlers`
|
|
|
|
feature flag:
|
|
|
|
|
|
|
|
```toml
|
|
|
|
[dependencies]
|
2016-12-05 15:23:00 -06:00
|
|
|
juniper = { version = "0.5.3", features = ["iron-handlers"] }
|
2016-09-11 11:41:29 -05:00
|
|
|
```
|
|
|
|
|
|
|
|
## Building schemas
|
|
|
|
|
|
|
|
GraphQL turns the REST paradigm as it's usually implemented on its head: instead
|
|
|
|
of providing a fixed structure of all types and relations in the system, GraphQL
|
|
|
|
defines a _schema_ which your users can query. The schema defines all types,
|
|
|
|
fields, and relations available, while the query defines which fields and
|
|
|
|
relations a user is interested in.
|
|
|
|
|
|
|
|
Juniper expects you to already have the types you want to expose in GraphQL as
|
|
|
|
Rust data types. Other than that, it doesn't make any assumptions whether they
|
|
|
|
are stored in a database or just in memory. Exposing a type is a matter of
|
|
|
|
implementing the `GraphQLType` for your type. To make things a bit easier,
|
|
|
|
Juniper comes with a set of macros that help you do this, based on what kind of
|
|
|
|
type you want to expose. Let's look at how one could expose parts of the [Star
|
|
|
|
Wars Schema][swschema]:
|
|
|
|
|
|
|
|
```rust
|
|
|
|
#[macro_use] extern crate juniper;
|
|
|
|
|
|
|
|
use juniper::FieldResult;
|
|
|
|
|
|
|
|
enum Episode {
|
|
|
|
NewHope,
|
|
|
|
Empire,
|
|
|
|
Jedi,
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Human {
|
|
|
|
id: String,
|
|
|
|
name: String,
|
|
|
|
appears_in: Vec<Episode>,
|
|
|
|
home_planet: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
graphql_enum!(Episode {
|
|
|
|
Episode::NewHope => "NEW_HOPE",
|
|
|
|
Episode::Empire => "EMPIRE",
|
|
|
|
Episode::Jedi => "JEDI",
|
|
|
|
});
|
|
|
|
|
2016-10-20 13:56:23 -05:00
|
|
|
graphql_object!(Human: () |&self| {
|
2016-09-11 11:41:29 -05:00
|
|
|
description: "A humanoid creature in the Star Wars universe"
|
|
|
|
|
|
|
|
// Field resolver methods look almost like ordinary methods. The macro picks
|
|
|
|
// up arguments and return types for the introspection schema, and verifies
|
|
|
|
// it during compilation.
|
|
|
|
field id() -> FieldResult<&String> {
|
|
|
|
Ok(&self.id)
|
|
|
|
}
|
|
|
|
|
|
|
|
field name() -> FieldResult<&String> {
|
|
|
|
Ok(&self.name)
|
|
|
|
}
|
|
|
|
|
|
|
|
field appears_in() -> FieldResult<&Vec<Episode>> {
|
|
|
|
Ok(&self.appears_in)
|
|
|
|
}
|
|
|
|
|
|
|
|
field home_planet() -> FieldResult<&String> {
|
|
|
|
Ok(&self.home_planet)
|
|
|
|
}
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
You can find the full example in [src/tests/schema.rs][test_schema_rs],
|
|
|
|
including polymorphism with traits and interfaces. For an example of the Iron
|
|
|
|
integration, see the [examples folder][examples].
|
|
|
|
|
|
|
|
## Features
|
|
|
|
|
|
|
|
Juniper supports the full GraphQL query language according to the
|
|
|
|
[specification][graphql_spec], including the introspective schema and all
|
|
|
|
validations. It does not, however, support the schema language.
|
|
|
|
|
|
|
|
As an exception to other GraphQL libraries for other languages, Juniper builds
|
|
|
|
non-null types by default. A field of type `Vec<Episode>` will be converted into
|
|
|
|
`[Episode!]!`. The corresponding Rust type for e.g. `[Episode]` would be
|
|
|
|
`Option<Vec<Option<Episode>>>`.
|
|
|
|
|
|
|
|
## API Stability
|
|
|
|
|
|
|
|
Juniper has not reached 1.0 yet, thus some API instability should be expected.
|
|
|
|
|
|
|
|
## 1.0 Roadmap
|
|
|
|
|
|
|
|
The road to 1.0 _focuses_ on two aspects: making sure the API hasn't got any
|
|
|
|
obvious dead-ends with respect to probable future features, and improving test
|
|
|
|
coverage for general execution. There are some chores that need to be completed
|
|
|
|
as well.
|
|
|
|
|
2016-11-13 03:41:46 -06:00
|
|
|
* [X] Extensive execution testing
|
|
|
|
* [X] Sending input objects and partial input objects in variables
|
|
|
|
* [X] Sending enums in variables
|
|
|
|
* [X] General input value type checking and validation
|
2016-10-19 13:58:36 -05:00
|
|
|
* [X] Improve helper macros
|
|
|
|
* [X] `graphql_union!` helper completely missing
|
2016-10-16 05:47:43 -05:00
|
|
|
* [X] `graphql_input_object!` helper completely missing
|
|
|
|
* [X] Add support for deprecating things
|
|
|
|
* [X] Custom enum values and descriptions
|
2016-10-16 09:02:40 -05:00
|
|
|
* [X] Improved syntax for fields that can't fail resolution - make
|
2016-09-11 11:41:29 -05:00
|
|
|
`FieldResult<T>` optional maybe?
|
2016-11-13 03:41:46 -06:00
|
|
|
* [X] Investigate asynchronous execution - implementing it is not necessary, but
|
2016-09-11 11:41:29 -05:00
|
|
|
at least look at what API changes will be needed for us to hook into
|
|
|
|
[Tokio][tokio], for example.
|
|
|
|
* [ ] Larger examples to illustrate things like database access
|
|
|
|
|
|
|
|
[graphql]: http://graphql.org
|
|
|
|
[iron]: http://ironframework.io
|
|
|
|
[swschema]: http://graphql.org/docs/typesystem/
|
|
|
|
[graphql_spec]: http://facebook.github.io/graphql
|
|
|
|
[test_schema_rs]: src/tests/schema.rs
|
|
|
|
[tokio]: https://github.com/tokio-rs/tokio
|
|
|
|
[examples]: examples/
|