diff --git a/master/advanced/dataloaders.html b/master/advanced/dataloaders.html index 363a4231..f72bb571 100644 --- a/master/advanced/dataloaders.html +++ b/master/advanced/dataloaders.html @@ -188,7 +188,7 @@ use std::env; pub fn get_db_conn() -> Connection { let pg_connection_string = env::var("DATABASE_URI").expect("need a db uri"); - println!("Connecting to {}", pg_connection_string); + println!("Connecting to {pg_connection_string}"); let conn = Connection::connect(&pg_connection_string[..], TlsMode::None).unwrap(); println!("Connection is fine"); conn @@ -221,7 +221,7 @@ impl BatchFn<i32, Cult> for CultBatcher { // A hashmap is used, as we need to return an array which maps each original key to a Cult. async fn load(&self, keys: &[i32]) -> HashMap<i32, Cult> { - println!("load cult batch {:?}", keys); + println!("load cult batch {keys:?}"); let mut cult_hashmap = HashMap::new(); get_cult_by_ids(&mut cult_hashmap, keys.to_vec()); cult_hashmap diff --git a/master/advanced/implicit_and_explicit_null.html b/master/advanced/implicit_and_explicit_null.html index e5083f97..bb669fb6 100644 --- a/master/advanced/implicit_and_explicit_null.html +++ b/master/advanced/implicit_and_explicit_null.html @@ -152,7 +152,7 @@ perform a "patch" operation on themselves. Let's say your users can optionally have favorite and least favorite numbers, and the input for that might look like this:
-/// Updates user attributes. Fields that are `None` are left as-is. +
/// Updates user attributes. Fields that are `None` are left as-is. pub struct UserPatch { /// If `Some`, updates the user's favorite number. pub favorite_number: Option<Option<i32>>, @@ -177,7 +177,7 @@ pub struct UserPatch {
The last two cases rely on being able to distinguish between explicit and implicit null.
In Juniper, this can be done using the
-Nullable
type:extern crate juniper; +
extern crate juniper; use juniper::{FieldResult, Nullable}; #[derive(juniper::GraphQLInputObject)] diff --git a/master/advanced/introspection.html b/master/advanced/introspection.html index b5228abf..63139015 100644 --- a/master/advanced/introspection.html +++ b/master/advanced/introspection.html @@ -157,7 +157,7 @@ produced by issuing a specially crafted introspection query.
Juniper provides a convenience function to introspect the entire schema. The result can then be converted to JSON for use with tools and libraries such as graphql-client:
-#![allow(unused_variables)] +
#![allow(unused_variables)] extern crate juniper; extern crate serde_json; use juniper::{ @@ -193,7 +193,7 @@ type Schema = juniper::RootNode< fn main() { // Create a context object. - let ctx = Context{}; + let ctx = Context; // Run the built-in introspection query. let (res, _errors) = juniper::introspect( diff --git a/master/advanced/non_struct_objects.html b/master/advanced/non_struct_objects.html index 65b62f8e..2b602abb 100644 --- a/master/advanced/non_struct_objects.html +++ b/master/advanced/non_struct_objects.html @@ -141,7 +141,7 @@ at enums, but traits will work too - they don't have to be mapped into interfaces.
Using
-Result
-like enums can be a useful way of reporting e.g. validation errors from a mutation:extern crate juniper; +
extern crate juniper; use juniper::{graphql_object, GraphQLObject}; #[derive(juniper::GraphQLObject)] struct User { name: String } diff --git a/master/advanced/objects_and_generics.html b/master/advanced/objects_and_generics.html index de2b7f06..f1907da8 100644 --- a/master/advanced/objects_and_generics.html +++ b/master/advanced/objects_and_generics.html @@ -144,7 +144,7 @@ not make e.g.
Result<T, E>
into a GraphQL type, but you cResult<User, String>
into a GraphQL type.Let's make a slightly more compact but generic implementation of the last chapter:
-extern crate juniper; +
extern crate juniper; #[derive(juniper::GraphQLObject)] struct User { name: String } #[derive(juniper::GraphQLObject)] struct ForumPost { title: String } diff --git a/master/advanced/subscriptions.html b/master/advanced/subscriptions.html index ebc277a1..78a1f54a 100644 --- a/master/advanced/subscriptions.html +++ b/master/advanced/subscriptions.html @@ -153,7 +153,7 @@ juniper_subscriptions = "0.17.0" operations in your Schema. For subscriptions all fields/operations should be async and should return a Stream.
This example shows a subscription operation that returns two events, the strings
-Hello
andWorld!
sequentially:use juniper::{graphql_object, graphql_subscription, FieldError}; +
use juniper::{graphql_object, graphql_subscription, FieldError}; use futures::Stream; use std::pin::Pin; @@ -194,7 +194,7 @@ and shutdown logic.
While you can implement
-SubscriptionCoordinator
yourself, Juniper contains a simple and generic implementation calledCoordinator
. Thesubscribe
operation returns aFuture
with anItem
value of aResult<Connection, GraphQLError>
, whereConnection
is aStream
of values returned by the operation andGraphQLError
is the error when the subscription fails.#![allow(dead_code)] +
#![allow(dead_code)] extern crate futures; extern crate juniper; extern crate juniper_subscriptions; @@ -217,7 +217,7 @@ where impl Database { fn new() -> Self { - Self {} + Self } } @@ -245,7 +245,7 @@ where graphql_object procedural macro that is used for declaring an object with resolvers, which you will use for the
Query
andMutation
roots. -#![allow(unused_variables)] +
#![allow(unused_variables)] extern crate juniper; use std::fmt::Display; use juniper::{ @@ -302,7 +302,7 @@ impl Mutation { type Schema = juniper::RootNode<'static, Query, Mutation, EmptySubscription<Context>>; fn main() { - let _ = Schema::new(Query, Mutation{}, EmptySubscription::new()); + let _ = Schema::new(Query, Mutation, EmptySubscription::new()); }
We now have a very simple but functional schema for a GraphQL server!
@@ -310,7 +310,7 @@ type Schema = juniper::RootNode<'static, Query, Mutation, EmptySubscription&lJuniper is a library that can be used in many contexts--it does not require a server and it does not have a dependency on a particular transport or serialization format. You can invoke the executor directly to get a result for a query:
Executor
You can invoke
-juniper::execute
directly to run a GraphQL query:// Only needed due to 2018 edition because the macro is not accessible. +
// Only needed due to 2018 edition because the macro is not accessible. #[macro_use] extern crate juniper; use juniper::{ graphql_object, EmptyMutation, EmptySubscription, FieldResult, @@ -395,7 +395,7 @@ is a struct. struct you want to expose, the easiest way is to use the custom derive attribute. The other way is described in the Complex fields chapter. -
extern crate juniper; +
extern crate juniper; use juniper::GraphQLObject; #[derive(GraphQLObject)] struct Person { @@ -414,7 +414,7 @@ fact that GraphQL is self-documenting and add descriptions to the type and fields. Juniper will automatically use associated doc comments as GraphQL descriptions:
!FILENAME GraphQL descriptions via Rust doc comments
-extern crate juniper; +
extern crate juniper; use juniper::GraphQLObject; #[derive(GraphQLObject)] /// Information about a person @@ -430,7 +430,7 @@ struct Person {
Objects and fields without doc comments can instead set a
description
via thegraphql
attribute. The following example is equivalent to the above:!FILENAME GraphQL descriptions via attribute
-extern crate juniper; +
extern crate juniper; use juniper::GraphQLObject; #[derive(GraphQLObject)] #[graphql(description = "Information about a person")] @@ -446,7 +446,7 @@ struct Person {
Descriptions set via the
-graphql
attribute take precedence over Rust doc comments. This enables internal Rust documentation and external GraphQL documentation to differ:extern crate juniper; +
extern crate juniper; use juniper::GraphQLObject; #[derive(GraphQLObject)] #[graphql(description = "This description shows up in GraphQL")] @@ -476,7 +476,7 @@ or
Let's see what that means for building relationships between objects:
-extern crate juniper; +
extern crate juniper; use juniper::GraphQLObject; #[derive(GraphQLObject)] struct Person { @@ -498,7 +498,7 @@ objects.
Renaming fields
By default, struct fields are converted from Rust's standard
-snake_case
naming convention into GraphQL'scamelCase
convention:extern crate juniper; +
extern crate juniper; use juniper::GraphQLObject; #[derive(GraphQLObject)] struct Person { @@ -510,7 +510,7 @@ struct Person {
You can override the name by using the
-graphql
attribute on individual struct fields:extern crate juniper; +
fn main() {}extern crate juniper; use juniper::GraphQLObject; #[derive(GraphQLObject)] struct Person { @@ -523,7 +523,7 @@ struct Person {
Or provide a different renaming policy on a struct for all its fields:
-extern crate juniper; +
extern crate juniper; use juniper::GraphQLObject; #[derive(GraphQLObject)] #[graphql(rename_all = "none")] // disables any renaming @@ -538,7 +538,7 @@ struct Person {
Deprecating fields
To deprecate a field, you specify a deprecation reason using the
-graphql
attribute:extern crate juniper; +
extern crate juniper; use juniper::GraphQLObject; #[derive(GraphQLObject)] struct Person { @@ -555,7 +555,7 @@ combined. Some restrictions from the GraphQL spec still applies though; you can only deprecate object fields and enum values.
Ignoring fields
By default, all fields in a
-GraphQLObject
are included in the generated GraphQL type. To prevent including a specific field, annotate the field with#[graphql(ignore)]
:extern crate juniper; +
extern crate juniper; use juniper::GraphQLObject; #[derive(GraphQLObject)] struct Person { @@ -578,7 +578,7 @@ you have to do so either in a separate "normal"
impl
bloc#[graphql(ignore)]
attribute to be omitted by the macro. Continuing with the example from the last chapter, this is how you would definePerson
using the macro: -#![allow(dead_code)] +
#![allow(dead_code)] extern crate juniper; use juniper::graphql_object; @@ -613,7 +613,7 @@ impl Person {
While this is a bit more verbose, it lets you write any kind of function in the field resolver. With this syntax, fields can also take arguments:
-extern crate juniper; +
extern crate juniper; use juniper::{graphql_object, GraphQLObject}; #[derive(GraphQLObject)] @@ -643,7 +643,7 @@ chapter: Using contexts.
Like with the derive attribute, field names will be converted from
-snake_case
tocamelCase
. If you need to override the conversion, you can simply rename the field. Also, the type name can be changed with an alias:extern crate juniper; +
fn main() { }extern crate juniper; use juniper::graphql_object; struct Person; @@ -689,7 +689,7 @@ impl Person {
Or provide a different renaming policy on a
-impl
block for all its fields:extern crate juniper; +
extern crate juniper; use juniper::graphql_object; struct Person; @@ -706,10 +706,10 @@ impl Person {
Customizing arguments
Method field arguments can also be customized.
They can have custom descriptions and default values.
-extern crate juniper; +
struct Person; #[graphql_object] impl Person { @@ -729,14 +729,14 @@ impl Person { #[graphql(default)] arg2: i32, ) -> String { - format!("{} {}", arg1, arg2) + format!("{arg1} {arg2}") } } fn main() { }extern crate juniper; use juniper::graphql_object; -struct Person {} +
Provide a different renaming policy on a
-impl
block also implies for arguments:extern crate juniper; +
extern crate juniper; use juniper::graphql_object; struct Person; @@ -761,7 +761,7 @@ documentation for either the Iro integration.
In this chapter, we'll show you how to define a context type and use it in field resolvers. Let's say that we have a simple user database in a
-HashMap
:#![allow(dead_code)] +
#![allow(dead_code)] use std::collections::HashMap; struct Database { @@ -782,7 +782,7 @@ In order to write such a field though, the database must be queried. the user object.
To gain access to the context, we need to specify an argument with the same type as the specified
-Context
for the type:extern crate juniper; +
extern crate juniper; use std::collections::HashMap; use juniper::graphql_object; @@ -832,7 +832,7 @@ using e.g.
RwLock
orRefCell
.Dealing with mutable references
Context cannot be specified by a mutable reference, because concurrent fields resolving may be performed. If you have something in your context that requires access by mutable reference, then you need to leverage the interior mutability for that.
For example, when using async runtime with work stealing (like
-tokio
), which obviously requires thread safety in addition, you will need to use a corresponding async version ofRwLock
:extern crate juniper; +
extern crate juniper; use std::collections::HashMap; use juniper::graphql_object; use tokio::sync::RwLock; @@ -894,7 +894,7 @@ it will bubble up to the surrounding framework and hopefully be dealt with there.
For recoverable errors, Juniper works well with the built-in
-Result
type, you can use the?
operator and things will generally just work as you expect them to:extern crate juniper; +
extern crate juniper; use std::{ str, path::PathBuf, @@ -982,7 +982,7 @@ following would be returned:
Structured errors
Sometimes it is desirable to return additional structured error information to clients. This can be accomplished by implementing
-IntoFieldError
:#[macro_use] extern crate juniper; +
#[macro_use] extern crate juniper; use juniper::{graphql_object, FieldError, IntoFieldError, ScalarValue}; enum CustomError { @@ -1047,7 +1047,7 @@ types. Strings are used to identify the problematic field name. Errors for a particular field are also returned as a string. In this example the string contains a server-side localized error message. However, it is also possible to return a unique string identifier and have the client present a localized string to the user. -
extern crate juniper; +
extern crate juniper; use juniper::{graphql_object, GraphQLObject, GraphQLUnion}; #[derive(GraphQLObject)] @@ -1082,15 +1082,15 @@ impl Mutation { if !(10 <= name.len() && name.len() <= 100) { errors.push(ValidationError { - field: "name".to_string(), - message: "between 10 and 100".to_string() + field: "name".into(), + message: "between 10 and 100".into(), }); } if !(1 <= quantity && quantity <= 10) { errors.push(ValidationError { - field: "quantity".to_string(), - message: "between 1 and 10".to_string() + field: "quantity".into(), + message: "between 1 and 10".into(), }); } @@ -1136,7 +1136,7 @@ GraphQL's type system to describe the errors more precisely. field is set if the validation for that particular field fails. You will likely want some kind of code generation to reduce repetition as the number of types required is significantly larger than before. Each resolver function has a custom
ValidationResult
which contains only fields provided by the function. -extern crate juniper; +
extern crate juniper; use juniper::{graphql_object, GraphQLObject, GraphQLUnion}; #[derive(GraphQLObject)] @@ -1168,11 +1168,11 @@ impl Mutation { }; if !(10 <= name.len() && name.len() <= 100) { - error.name = Some("between 10 and 100".to_string()); + error.name = Some("between 10 and 100".into()); } if !(1 <= quantity && quantity <= 10) { - error.quantity = Some("between 1 and 10".to_string()); + error.quantity = Some("between 1 and 10".into()); } if error.name.is_none() && error.quantity.is_none() { @@ -1208,7 +1208,7 @@ errors when they occur.
In the following example, a theoretical database could fail and would generate errors. Since it is not common for the database to fail, the corresponding error is returned as a critical error:
-extern crate juniper; +
extern crate juniper; use juniper::{graphql_object, graphql_value, FieldError, GraphQLObject, GraphQLUnion, ScalarValue}; @@ -1258,11 +1258,11 @@ impl Mutation { }; if !(10 <= name.len() && name.len() <= 100) { - error.name = Some("between 10 and 100".to_string()); + error.name = Some("between 10 and 100".into()); } if !(1 <= quantity && quantity <= 10) { - error.quantity = Some("between 1 and 10".to_string()); + error.quantity = Some("between 1 and 10".into()); } if error.name.is_none() && error.quantity.is_none() { @@ -1296,7 +1296,7 @@ explore this approach in a real world application.
Enums in GraphQL are string constants grouped together to represent a set of possible values. Simple Rust enums can be converted to GraphQL enums by using a custom derive attribute:
-extern crate juniper; +
extern crate juniper; #[derive(juniper::GraphQLEnum)] enum Episode { NewHope, @@ -1310,7 +1310,7 @@ enum Episode { values for these variants are
NEWHOPE
,EMPIRE
, andJEDI
, respectively. If you want to override this, you can use thegraphql
attribute, similar to how it works when defining objects: -extern crate juniper; +
extern crate juniper; #[derive(juniper::GraphQLEnum)] enum Episode { #[graphql(name="NEW_HOPE")] @@ -1324,7 +1324,7 @@ enum Episode {
Documentation and deprecation
Just like when defining objects, the type itself can be renamed and documented, while individual enum variants can be renamed, documented, and deprecated:
-extern crate juniper; +
extern crate juniper; #[derive(juniper::GraphQLEnum)] #[graphql(name="Episode", description="An episode of Star Wars")] enum StarWarsEpisode { @@ -1358,7 +1358,7 @@ enum StarWarsEpisode {
For implementing GraphQL interfaces Juniper provides the
#[graphql_interface]
macro.Traits
Defining a trait is mandatory for defining a GraphQL interface, because this is the obvious way we describe an abstraction in Rust. All interface fields are defined as computed ones via trait methods.
-extern crate juniper; +
extern crate juniper; use juniper::graphql_interface; #[graphql_interface] @@ -1371,7 +1371,7 @@ trait Character {
However, to return values of such interface, we should provide its implementers and the Rust type representing a boxed value of this trait. The last one can be represented in two flavors: enum and trait object.
Enum values (default)
By default, Juniper generates an enum representing the values of the defined GraphQL interface, and names it straightforwardly,
-{Interface}Value
.extern crate juniper; +
fn main() {}extern crate juniper; use juniper::{graphql_interface, GraphQLObject}; #[graphql_interface(for = [Human, Droid])] // enumerating all implementers is mandatory @@ -1394,7 +1394,7 @@ struct Droid {
Also, enum name can be specified explicitly, if desired.
-extern crate juniper; +
extern crate juniper; use juniper::{graphql_interface, GraphQLObject}; #[graphql_interface(enum = CharaterInterface, for = Human)] @@ -1413,7 +1413,7 @@ struct Human {
Interfaces implementing other interfaces
GraphQL allows implementing interfaces on other interfaces in addition to objects.
-extern crate juniper; +
extern crate juniper; use juniper::{graphql_interface, graphql_object, ID}; #[graphql_interface(for = [HumanValue, Luke])] @@ -1487,7 +1487,7 @@ fn main() {}
These rules are recursively applied, so
Vec<Vec<I implements T>>
is a valid "subtype" of aOption<Vec<Option<Vec<Option<T>>>>>
.Also, GraphQL allows implementers to add
-null
able fields, which aren't present on an original interface.extern crate juniper; +
extern crate juniper; use juniper::{graphql_interface, graphql_object, ID}; #[graphql_interface(for = [HumanValue, Luke])] @@ -1554,7 +1554,7 @@ impl ObjA { // ^^ the evaluated program panicked at // 'Failed to implement interface `Character` on `ObjA`: Field `id`: Argument `isPresent` of type `Boolean!` // isn't present on the interface and so has to be nullable.' - is_present.then(|| self.id.as_str()).unwrap_or("missing") + is_present.then_some(&self.id).unwrap_or("missing") } } @@ -1586,7 +1586,7 @@ struct Character {
Ignoring trait methods
We may want to omit some trait methods to be assumed as GraphQL interface fields and ignore them.
-extern crate juniper; +
extern crate juniper; use juniper::{graphql_interface, GraphQLObject}; #[graphql_interface(for = Human)] @@ -1607,7 +1607,7 @@ struct Human {
Fields, arguments and interface customization
Similarly to GraphQL objects Juniper allows to fully customize interface fields and their arguments.
-#![allow(deprecated)] +
fn main() {}#![allow(deprecated)] extern crate juniper; use juniper::graphql_interface; @@ -1647,7 +1647,7 @@ trait Character {
Renaming policies for all GraphQL interface fields and arguments are supported as well:
-#![allow(deprecated)] +
#![allow(deprecated)] extern crate juniper; use juniper::graphql_interface; @@ -1661,7 +1661,7 @@ trait Character {
Custom context
If a
-Context
is required in a trait method to resolve a GraphQL interface field, specify it as an argument.extern crate juniper; +
extern crate juniper; use std::collections::HashMap; use juniper::{graphql_interface, GraphQLObject}; @@ -1692,7 +1692,7 @@ struct Human {
Using executor and explicit generic scalar
If an
Executor
is required in a trait method to resolve a GraphQL interface field, specify it as an argument.This requires to explicitly parametrize over
-ScalarValue
, asExecutor
does so.extern crate juniper; +
extern crate juniper; use juniper::{graphql_interface, graphql_object, Executor, LookAheadMethods as _, ScalarValue}; #[graphql_interface(for = Human, Scalar = S)] // notice specifying `ScalarValue` as existing type parameter @@ -1738,7 +1738,7 @@ impl Human {
ScalarValue
considerationsBy default,
-#[graphql_interface]
macro generates code, which is generic over aScalarValue
type. This may introduce a problem when at least one of GraphQL interface implementers is restricted to a concreteScalarValue
type in its implementation. To resolve such problem, a concreteScalarValue
type should be specified.extern crate juniper; +
extern crate juniper; use juniper::{graphql_interface, DefaultScalarValue, GraphQLObject}; #[graphql_interface(for = [Human, Droid])] @@ -1767,7 +1767,7 @@ struct Droid {
Input objects are complex data structures that can be used as arguments to GraphQL fields. In Juniper, you can define input objects using a custom derive attribute, similar to simple objects and enums:
-