Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #372 from codri/update_graphql_example_to_new_juni…
…per_api Updated graphql example to use the new Juniper API, as well as added …
- Loading branch information
Showing
1 changed file
with
107 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
use async_std::task; | ||
use juniper::RootNode; | ||
use std::sync::RwLock; | ||
use tide::{Request, Response, Server}; | ||
|
||
#[derive(Clone)] | ||
struct User { | ||
id: Option<u16>, | ||
first_name: String, | ||
} | ||
|
||
#[juniper::object] | ||
#[graphql(description = "A user")] | ||
impl User { | ||
#[graphql(description = "A user id")] | ||
fn id(&self) -> i32 { | ||
self.id.unwrap_or(0) as i32 | ||
} | ||
|
||
#[graphql(description = "A user first_name")] | ||
fn first_name(&self) -> &str { | ||
&self.first_name | ||
} | ||
} | ||
|
||
#[derive(juniper::GraphQLInputObject)] | ||
struct NewUser { | ||
first_name: String, | ||
} | ||
|
||
impl NewUser { | ||
fn to_internal(self) -> User { | ||
User { | ||
id: None, | ||
first_name: self.first_name.to_owned(), | ||
} | ||
} | ||
} | ||
|
||
pub struct State { | ||
users: RwLock<Vec<User>>, | ||
} | ||
impl juniper::Context for State {} | ||
|
||
pub struct QueryRoot; | ||
|
||
#[juniper::object(Context=State)] | ||
impl QueryRoot { | ||
#[graphql(description = "Get all Users")] | ||
fn users(context: &State) -> Vec<User> { | ||
let users = context.users.read().unwrap(); | ||
users.iter().map(|u| u.clone()).collect() | ||
} | ||
} | ||
|
||
pub struct MutationRoot; | ||
|
||
#[juniper::object(Context=State)] | ||
impl MutationRoot { | ||
#[graphql(description = "Add new user")] | ||
fn add_user(context: &State, user: NewUser) -> User { | ||
let mut users = context.users.write().unwrap(); | ||
let mut user = user.to_internal(); | ||
user.id = Some((users.len() + 1) as u16); | ||
users.push(user.clone()); | ||
user | ||
} | ||
} | ||
|
||
pub type Schema = RootNode<'static, QueryRoot, MutationRoot>; | ||
fn create_schema() -> Schema { | ||
Schema::new(QueryRoot {}, MutationRoot {}) | ||
} | ||
|
||
async fn handle_graphql(mut cx: Request<State>) -> Response { | ||
let query: juniper::http::GraphQLRequest = cx | ||
.body_json() | ||
.await | ||
.expect("be able to deserialize the graphql request"); | ||
|
||
let schema = create_schema(); // probably worth making the schema a singleton using lazy_static library | ||
let response = query.execute(&schema, cx.state()); | ||
let status = if response.is_ok() { 200 } else { 400 }; | ||
|
||
Response::new(status) | ||
.body_json(&response) | ||
.expect("be able to serialize the graphql response") | ||
} | ||
|
||
async fn handle_graphiql(_: Request<State>) -> Response { | ||
Response::new(200) | ||
.body_string(juniper::http::graphiql::graphiql_source("/graphql")) | ||
.set_header("content-type", "text/html;charset=utf-8") | ||
} | ||
|
||
fn main() -> std::io::Result<()> { | ||
task::block_on(async { | ||
let mut app = Server::with_state(State { | ||
users: RwLock::new(Vec::new()), | ||
}); | ||
app.at("/").get(tide::redirect("/graphiql")); | ||
app.at("/graphql").post(handle_graphql); | ||
app.at("/graphiql").get(handle_graphiql); | ||
app.listen("0.0.0.0:8080").await?; | ||
Ok(()) | ||
}) | ||
} |