Skip to content

Commit 94d689f

Browse files
committed
Initial import
0 parents  commit 94d689f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+16729
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
target
2+
Cargo.lock

.travis.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
language: rust
2+
3+
rust:
4+
- stable
5+
- beta
6+
- nightly
7+
matrix:
8+
allow_failures:
9+
- rust: nightly
10+
11+
script:
12+
cargo build --verbose
13+
cargo build --features iron-handlers --verbose
14+
15+
cargo test --verbose --features iron-handlers

Cargo.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[package]
2+
name = "juniper"
3+
version = "0.1.0"
4+
authors = ["Magnus Hallin <[email protected]>"]
5+
6+
[features]
7+
default = []
8+
nightly = []
9+
iron-handlers = ["iron"]
10+
11+
[dependencies]
12+
rustc-serialize = "0.3.19"
13+
iron = { version = "^0.4.0", optional = true }
14+
15+
[dev-dependencies]
16+
iron = "^0.4.0"
17+
router = "^0.2.0"
18+
mount = "^0.2.1"
19+
logger = "^0.1.0"
20+
iron-test = "^0.4.0"

LICENSE

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
BSD 2-Clause License
2+
3+
Copyright (c) 2016, Magnus Hallin
4+
All rights reserved.
5+
6+
Redistribution and use in source and binary forms, with or without
7+
modification, are permitted provided that the following conditions are met:
8+
9+
* Redistributions of source code must retain the above copyright notice, this
10+
list of conditions and the following disclaimer.
11+
12+
* Redistributions in binary form must reproduce the above copyright notice,
13+
this list of conditions and the following disclaimer in the documentation
14+
and/or other materials provided with the distribution.
15+
16+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

README.md

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# Juniper
2+
3+
> GraphQL server library for Rust
4+
5+
---
6+
7+
[GraphQL][graphql] is a data query language developed by Facebook intended to
8+
serve mobile and web application frontends. Juniper makes it possible to write
9+
GraphQL servers in Rust that are type-safe and blazingly fast.
10+
11+
Juniper does not include a web server - instead it provides building blocks to
12+
make integration with existing servers straightforward. It optionally provides a
13+
pre-built integration for the [Iron framework][iron].
14+
15+
## Installation
16+
17+
Add Juniper to your Cargo.toml:
18+
19+
```toml
20+
[dependencies]
21+
juniper = "0.5.0"
22+
```
23+
24+
If you want the Iron integration enabled, you need to enable the `iron-handlers`
25+
feature flag:
26+
27+
```toml
28+
[dependencies]
29+
juniper = { version = "0.5.0", features = ["iron-handlers"] }
30+
```
31+
32+
## Building schemas
33+
34+
GraphQL turns the REST paradigm as it's usually implemented on its head: instead
35+
of providing a fixed structure of all types and relations in the system, GraphQL
36+
defines a _schema_ which your users can query. The schema defines all types,
37+
fields, and relations available, while the query defines which fields and
38+
relations a user is interested in.
39+
40+
Juniper expects you to already have the types you want to expose in GraphQL as
41+
Rust data types. Other than that, it doesn't make any assumptions whether they
42+
are stored in a database or just in memory. Exposing a type is a matter of
43+
implementing the `GraphQLType` for your type. To make things a bit easier,
44+
Juniper comes with a set of macros that help you do this, based on what kind of
45+
type you want to expose. Let's look at how one could expose parts of the [Star
46+
Wars Schema][swschema]:
47+
48+
```rust
49+
#[macro_use] extern crate juniper;
50+
51+
use juniper::FieldResult;
52+
53+
enum Episode {
54+
NewHope,
55+
Empire,
56+
Jedi,
57+
}
58+
59+
struct Human {
60+
id: String,
61+
name: String,
62+
appears_in: Vec<Episode>,
63+
home_planet: String,
64+
}
65+
66+
graphql_enum!(Episode {
67+
Episode::NewHope => "NEW_HOPE",
68+
Episode::Empire => "EMPIRE",
69+
Episode::Jedi => "JEDI",
70+
});
71+
72+
graphql_object!(Human: () as "Human" |&self| {
73+
description: "A humanoid creature in the Star Wars universe"
74+
75+
// Field resolver methods look almost like ordinary methods. The macro picks
76+
// up arguments and return types for the introspection schema, and verifies
77+
// it during compilation.
78+
field id() -> FieldResult<&String> {
79+
Ok(&self.id)
80+
}
81+
82+
field name() -> FieldResult<&String> {
83+
Ok(&self.name)
84+
}
85+
86+
field appears_in() -> FieldResult<&Vec<Episode>> {
87+
Ok(&self.appears_in)
88+
}
89+
90+
field home_planet() -> FieldResult<&String> {
91+
Ok(&self.home_planet)
92+
}
93+
});
94+
```
95+
96+
You can find the full example in [src/tests/schema.rs][test_schema_rs],
97+
including polymorphism with traits and interfaces. For an example of the Iron
98+
integration, see the [examples folder][examples].
99+
100+
## Features
101+
102+
Juniper supports the full GraphQL query language according to the
103+
[specification][graphql_spec], including the introspective schema and all
104+
validations. It does not, however, support the schema language.
105+
106+
As an exception to other GraphQL libraries for other languages, Juniper builds
107+
non-null types by default. A field of type `Vec<Episode>` will be converted into
108+
`[Episode!]!`. The corresponding Rust type for e.g. `[Episode]` would be
109+
`Option<Vec<Option<Episode>>>`.
110+
111+
## API Stability
112+
113+
Juniper has not reached 1.0 yet, thus some API instability should be expected.
114+
115+
## 1.0 Roadmap
116+
117+
The road to 1.0 _focuses_ on two aspects: making sure the API hasn't got any
118+
obvious dead-ends with respect to probable future features, and improving test
119+
coverage for general execution. There are some chores that need to be completed
120+
as well.
121+
122+
* [ ] Extensive execution testing
123+
* [ ] Sending input objects and partial input objects in variables
124+
* [ ] Sending enums in variables
125+
* [ ] General input value type checking and validation
126+
* [ ] Improve helper macros
127+
* [ ] `graphql_union!` helper completely missing
128+
* [ ] Add support for deprecating things
129+
* [ ] Custom enum values and descriptions
130+
* [ ] Improved syntax for fields that can't fail resolution - make
131+
`FieldResult<T>` optional maybe?
132+
* [ ] Investigate asynchronous execution - implementing it is not necessary, but
133+
at least look at what API changes will be needed for us to hook into
134+
[Tokio][tokio], for example.
135+
* [ ] Larger examples to illustrate things like database access
136+
137+
[graphql]: http://graphql.org
138+
[iron]: http://ironframework.io
139+
[swschema]: http://graphql.org/docs/typesystem/
140+
[graphql_spec]: http://facebook.github.io/graphql
141+
[test_schema_rs]: src/tests/schema.rs
142+
[tokio]: https://github.com/tokio-rs/tokio
143+
[examples]: examples/

examples/server.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
extern crate iron;
2+
extern crate mount;
3+
extern crate logger;
4+
extern crate rustc_serialize;
5+
#[macro_use] extern crate juniper;
6+
7+
use mount::Mount;
8+
use logger::Logger;
9+
use iron::prelude::*;
10+
use juniper::FieldResult;
11+
use juniper::iron_handlers::{GraphQLHandler, GraphiQLHandler};
12+
13+
fn context_factory(_: &mut Request) -> () {
14+
()
15+
}
16+
17+
fn main() {
18+
let mut mount = Mount::new();
19+
20+
let graphql_endpoint = GraphQLHandler::new(context_factory, Query { }, Mutation { });
21+
let graphiql_endpoint = GraphiQLHandler::new("/graphql");
22+
23+
mount.mount("/graphiql", graphiql_endpoint);
24+
mount.mount("/graphql", graphql_endpoint);
25+
26+
let (logger_before, logger_after) = Logger::new(None);
27+
28+
let mut chain = Chain::new(mount);
29+
chain.link_before(logger_before);
30+
chain.link_after(logger_after);
31+
32+
let host = "localhost:8080";
33+
println!("GraphQL server started on {}", host);
34+
Iron::new(chain).http(host).unwrap();
35+
}
36+
37+
struct Query {}
38+
struct Mutation {}
39+
40+
graphql_object!(Query: () as "Query" |&self| {
41+
field dummy() -> FieldResult<&str> {
42+
Ok("Dummy field")
43+
}
44+
45+
field error() -> FieldResult<&str> {
46+
Err("Can't do it".to_owned())
47+
}
48+
});
49+
50+
graphql_object!(<CtxT> Mutation: CtxT as "Mutation" |&self| {
51+
field print(value: String) -> FieldResult<String> {
52+
println!("Printing text according to mutation");
53+
println!("{}", value);
54+
Ok(value)
55+
}
56+
});

0 commit comments

Comments
 (0)