diff --git a/Cargo.lock b/Cargo.lock index 6ca53a0..a05ef60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -705,6 +705,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +[[package]] +name = "ascii" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" + [[package]] name = "askama" version = "0.9.0" @@ -1598,6 +1604,19 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "combine" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" +dependencies = [ + "ascii", + "byteorder", + "either", + "memchr", + "unreachable", +] + [[package]] name = "combine" version = "4.4.0" @@ -2362,6 +2381,17 @@ version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94" +[[package]] +name = "futures-enum" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3422d14de7903a52e9dbc10ae05a7e14445ec61890100e098754e120b2bd7b1e" +dependencies = [ + "derive_utils", + "quote", + "syn", +] + [[package]] name = "futures-executor" version = "0.3.13" @@ -2540,6 +2570,16 @@ dependencies = [ "web-sys", ] +[[package]] +name = "graphql-parser" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1abd4ce5247dfc04a03ccde70f87a048458c9356c7e41d21ad8c407b3dde6f2" +dependencies = [ + "combine 3.8.1", + "thiserror", +] + [[package]] name = "h2" version = "0.2.7" @@ -2957,18 +2997,24 @@ dependencies = [ [[package]] name = "juniper" -version = "0.14.2" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f662ba51e2fbc3d6dd1ca66be70b44963606a34473156abddcb0351fc6caa668" +checksum = "4e1330b4b3b2fe7de256fd08738f7fba28ffa574109c834988c28972f0760dbd" dependencies = [ + "async-trait", + "bson", "chrono", "fnv", + "futures", + "futures-enum", + "graphql-parser", "indexmap", "juniper_codegen", "serde 1.0.117", - "serde_derive", + "smartstring", + "static_assertions 1.1.0", "url", - "uuid 0.7.4", + "uuid 0.8.1", ] [[package]] @@ -3003,10 +3049,11 @@ dependencies = [ [[package]] name = "juniper_codegen" -version = "0.14.2" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d40af234d8e971a9d7dda93ffbcc8a44a93f17e69e3067f72ce7a6894c41d51b" +checksum = "3faf2a1e2e86cadc6bcc6082d63c73e8eafe6b703a0c5723e585b3d4afcec9cd" dependencies = [ + "proc-macro-error", "proc-macro2", "quote", "syn", @@ -3988,6 +4035,30 @@ dependencies = [ "toml", ] +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check 0.9.2", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check 0.9.2", +] + [[package]] name = "proc-macro-hack" version = "0.5.19" @@ -4002,9 +4073,9 @@ checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a" [[package]] name = "proc-macro2" -version = "1.0.24" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" dependencies = [ "unicode-xid", ] @@ -4214,7 +4285,7 @@ checksum = "7b94c6247d45d78d24481a5b7aca146f414ec0f5e39e175f294d1876b943eeeb" dependencies = [ "async-trait", "bytes 0.5.6", - "combine", + "combine 4.4.0", "dtoa", "futures-util", "itoa", @@ -4952,6 +5023,15 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7acad6f34eb9e8a259d3283d1e8c1d34d7415943d4895f65cc73813c7396fc85" +[[package]] +name = "smartstring" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ada87540bf8ef4cf8a1789deb175626829bb59b1fefd816cf7f7f55efcdbae9" +dependencies = [ + "static_assertions 1.1.0", +] + [[package]] name = "socket2" version = "0.3.17" @@ -5225,9 +5305,9 @@ checksum = "343f3f510c2915908f155e94f17220b19ccfacf2a64a2a5d8004f2c3e311e7fd" [[package]] name = "syn" -version = "1.0.53" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8833e20724c24de12bbaba5ad230ea61c3eafb05b881c7c9d3cfe8638b187e68" +checksum = "b9505f307c872bab8eb46f77ae357c8eba1fdacead58ee5a850116b1d7f82883" dependencies = [ "proc-macro2", "quote", @@ -5930,6 +6010,15 @@ dependencies = [ "env_logger 0.8.2", ] +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +dependencies = [ + "void", +] + [[package]] name = "untrusted" version = "0.7.1" @@ -5963,12 +6052,6 @@ dependencies = [ "cfg-if 0.1.10", ] -[[package]] -name = "uuid" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" - [[package]] name = "uuid" version = "0.8.1" diff --git a/graphql/juniper-advanced/Cargo.toml b/graphql/juniper-advanced/Cargo.toml index 0098539..9ad49a1 100644 --- a/graphql/juniper-advanced/Cargo.toml +++ b/graphql/juniper-advanced/Cargo.toml @@ -9,7 +9,7 @@ edition = "2018" [dependencies] actix-web = "3" -juniper = "0.14" +juniper = "0.15" mysql = "17" r2d2 = "0.8" diff --git a/graphql/juniper-advanced/README.md b/graphql/juniper-advanced/README.md index 9314608..a41b1e7 100644 --- a/graphql/juniper-advanced/README.md +++ b/graphql/juniper-advanced/README.md @@ -2,18 +2,18 @@ GraphQL Implementation in Rust using Actix, Juniper, and Mysql as Database -# Prerequites +## Prerequisites + - Rust Installed - MySql as Database -# Database Configuration +## Database Configuration Create a new database for this project, and import the existing database schema has been provided named ```mysql-schema.sql```. Create ```.env``` file on the root directory of this project and set environment variable named ```DATABASE_URL```, the example file has been provided named ```.env.example```, you can see the format on there. -# Run - +## Run ```sh # go to the root dir @@ -23,6 +23,6 @@ cd juniper-advanced cargo run ``` -### GraphQL Playground +## GraphQL Playground -http://127.0.0.1:8080/graphiql + diff --git a/graphql/juniper-advanced/src/handlers.rs b/graphql/juniper-advanced/src/handlers.rs index 5ac2a29..0177f8e 100644 --- a/graphql/juniper-advanced/src/handlers.rs +++ b/graphql/juniper-advanced/src/handlers.rs @@ -14,7 +14,7 @@ pub async fn graphql( dbpool: pool.get_ref().to_owned(), }; let res = web::block(move || { - let res = data.execute(&schema, &ctx); + let res = data.execute_sync(&schema, &ctx); Ok::<_, serde_json::error::Error>(serde_json::to_string(&res)?) }) .await @@ -28,7 +28,7 @@ pub async fn graphql( pub async fn graphql_playground() -> HttpResponse { HttpResponse::Ok() .content_type("text/html; charset=utf-8") - .body(graphiql_source("/graphql")) + .body(graphiql_source("/graphql", None)) } pub fn register(config: &mut web::ServiceConfig) { diff --git a/graphql/juniper-advanced/src/schemas/product.rs b/graphql/juniper-advanced/src/schemas/product.rs index 9304ff3..47a79aa 100644 --- a/graphql/juniper-advanced/src/schemas/product.rs +++ b/graphql/juniper-advanced/src/schemas/product.rs @@ -12,7 +12,7 @@ pub struct Product { pub price: f64, } -#[juniper::object(Context = Context)] +#[juniper::graphql_object(Context = Context)] impl Product { fn id(&self) -> &str { &self.id @@ -33,7 +33,7 @@ impl Product { "SELECT * FROM user WHERE id=:id", params! {"id" => &self.user_id}, ); - if let Err(err) = user { + if let Err(_err) = user { None } else { let (id, name, email) = from_row(user.unwrap().unwrap()); diff --git a/graphql/juniper-advanced/src/schemas/root.rs b/graphql/juniper-advanced/src/schemas/root.rs index 051ef49..8302fb2 100644 --- a/graphql/juniper-advanced/src/schemas/root.rs +++ b/graphql/juniper-advanced/src/schemas/root.rs @@ -1,4 +1,4 @@ -use juniper::{FieldError, FieldResult, RootNode}; +use juniper::{EmptySubscription, FieldError, FieldResult, RootNode}; use mysql::{from_row, params, Error as DBError, Row}; use crate::db::Pool; @@ -14,7 +14,7 @@ impl juniper::Context for Context {} pub struct QueryRoot; -#[juniper::object(Context = Context)] +#[juniper::graphql_object(Context = Context)] impl QueryRoot { #[graphql(description = "List of all users")] fn users(context: &Context) -> FieldResult> { @@ -24,7 +24,7 @@ impl QueryRoot { .map(|result| { result .map(|x| x.unwrap()) - .map(|mut row| { + .map(|row| { let (id, name, email) = from_row(row); User { id, name, email } }) @@ -41,7 +41,7 @@ impl QueryRoot { let user: Result, DBError> = conn.first_exec("SELECT * FROM user WHERE id=:id", params! {"id" => id}); - if let Err(err) = user { + if let Err(_err) = user { return Err(FieldError::new( "User Not Found", graphql_value!({ "not_found": "user not found" }), @@ -60,7 +60,7 @@ impl QueryRoot { .map(|result| { result .map(|x| x.unwrap()) - .map(|mut row| { + .map(|row| { let (id, user_id, name, price) = from_row(row); Product { id, @@ -80,7 +80,7 @@ impl QueryRoot { let mut conn = context.dbpool.get().unwrap(); let product: Result, DBError> = conn.first_exec("SELECT * FROM user WHERE id=:id", params! {"id" => id}); - if let Err(err) = product { + if let Err(_err) = product { return Err(FieldError::new( "Product Not Found", graphql_value!({ "not_found": "product not found" }), @@ -99,7 +99,7 @@ impl QueryRoot { pub struct MutationRoot; -#[juniper::object(Context = Context)] +#[juniper::graphql_object(Context = Context)] impl MutationRoot { fn create_user(context: &Context, user: UserInput) -> FieldResult { let mut conn = context.dbpool.get().unwrap(); @@ -115,7 +115,7 @@ impl MutationRoot { ); match insert { - Ok(opt_row) => Ok(User { + Ok(_opt_row) => Ok(User { id: new_id, name: user.name, email: user.email, @@ -148,7 +148,7 @@ impl MutationRoot { ); match insert { - Ok(opt_row) => Ok(Product { + Ok(_opt_row) => Ok(Product { id: new_id, user_id: product.user_id, name: product.name, @@ -168,8 +168,8 @@ impl MutationRoot { } } -pub type Schema = RootNode<'static, QueryRoot, MutationRoot>; +pub type Schema = RootNode<'static, QueryRoot, MutationRoot, EmptySubscription>; pub fn create_schema() -> Schema { - Schema::new(QueryRoot, MutationRoot) + Schema::new(QueryRoot, MutationRoot, EmptySubscription::new()) } diff --git a/graphql/juniper-advanced/src/schemas/user.rs b/graphql/juniper-advanced/src/schemas/user.rs index d17e293..0776c0a 100644 --- a/graphql/juniper-advanced/src/schemas/user.rs +++ b/graphql/juniper-advanced/src/schemas/user.rs @@ -18,7 +18,7 @@ pub struct UserInput { pub email: String, } -#[juniper::object(Context = Context)] +#[juniper::graphql_object(Context = Context)] impl User { fn id(&self) -> &str { &self.id @@ -42,7 +42,7 @@ impl User { .map(|result| { result .map(|x| x.unwrap()) - .map(|mut row| { + .map(|row| { let (id, user_id, name, price) = from_row(row); Product { id, diff --git a/graphql/juniper/Cargo.toml b/graphql/juniper/Cargo.toml index b2477c4..f5dacf4 100644 --- a/graphql/juniper/Cargo.toml +++ b/graphql/juniper/Cargo.toml @@ -11,4 +11,4 @@ env_logger = "0.8" serde = "1.0.103" serde_json = "1.0.44" serde_derive = "1.0.103" -juniper = "0.14.2" +juniper = "0.15" diff --git a/graphql/juniper/README.md b/graphql/juniper/README.md index c61b9b1..eb075e6 100644 --- a/graphql/juniper/README.md +++ b/graphql/juniper/README.md @@ -20,6 +20,7 @@ cargo run (or ``cargo watch -x run``) [http://127.0.0.1:8080/graphiql](http://127.0.0.1:8080/graphiql) _Query example:_ + ```graphql { human(id: "1234") { @@ -29,7 +30,9 @@ _Query example:_ } } ``` + _Result:_ + ```json { "data": { @@ -58,6 +61,7 @@ mutation { ``` _Result:_ + ```json { "data": { diff --git a/graphql/juniper/src/main.rs b/graphql/juniper/src/main.rs index ad4c664..4a790e2 100644 --- a/graphql/juniper/src/main.rs +++ b/graphql/juniper/src/main.rs @@ -14,7 +14,7 @@ mod schema; use crate::schema::{create_schema, Schema}; async fn graphiql() -> HttpResponse { - let html = graphiql_source("http://127.0.0.1:8080/graphql"); + let html = graphiql_source("http://127.0.0.1:8080/graphql", None); HttpResponse::Ok() .content_type("text/html; charset=utf-8") .body(html) @@ -25,7 +25,7 @@ async fn graphql( data: web::Json, ) -> Result { let user = web::block(move || { - let res = data.execute(&st, &()); + let res = data.execute_sync(&st, &()); Ok::<_, serde_json::error::Error>(serde_json::to_string(&res)?) }) .await?; diff --git a/graphql/juniper/src/schema.rs b/graphql/juniper/src/schema.rs index cbec139..8200d60 100644 --- a/graphql/juniper/src/schema.rs +++ b/graphql/juniper/src/schema.rs @@ -1,5 +1,5 @@ use juniper::FieldResult; -use juniper::RootNode; +use juniper::{EmptySubscription, RootNode}; #[derive(GraphQLEnum)] enum Episode { @@ -29,9 +29,9 @@ struct NewHuman { pub struct QueryRoot; -#[juniper::object] +#[juniper::graphql_object] impl QueryRoot { - fn human(id: String) -> FieldResult { + fn human(_id: String) -> FieldResult { Ok(Human { id: "1234".to_owned(), name: "Luke".to_owned(), @@ -43,7 +43,7 @@ impl QueryRoot { pub struct MutationRoot; -#[juniper::object] +#[juniper::graphql_object] impl MutationRoot { fn create_human(new_human: NewHuman) -> FieldResult { Ok(Human { @@ -55,8 +55,8 @@ impl MutationRoot { } } -pub type Schema = RootNode<'static, QueryRoot, MutationRoot>; +pub type Schema = RootNode<'static, QueryRoot, MutationRoot, EmptySubscription>; pub fn create_schema() -> Schema { - Schema::new(QueryRoot {}, MutationRoot {}) + Schema::new(QueryRoot {}, MutationRoot {}, EmptySubscription::new()) }