diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1277ce0d..fe6b3df6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: fail-fast: false matrix: include: -# - { rust: stable, os: ubuntu-latest } + # - { rust: stable, os: ubuntu-latest } - { rust: 1.56.1, os: ubuntu-latest } steps: - name: Checkout @@ -55,7 +55,7 @@ jobs: override: true components: rustfmt - name: Check format - run: cargo fmt --all -- --check + run: cargo +nightly fmt --all -- --check clippy: name: Run clippy - Rust (${{ matrix.rust }}) on ${{ matrix.os }} @@ -108,7 +108,6 @@ jobs: - name: Clean examples run: cargo clean working-directory: ./examples - # build-nightly: # name: Build nightly - Rust (${{ matrix.rust }}) on ${{ matrix.os }} # runs-on: ${{ matrix.os }} diff --git a/.rustfmt.toml b/.rustfmt.toml index 9d25d3fc..88af0ae5 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,2 +1,12 @@ edition = "2021" newline_style = "unix" +# comments +normalize_comments=true +wrap_comments=true +format_code_in_doc_comments=true +# imports +imports_granularity="Crate" +group_imports="StdExternalCrate" +# report +#report_fixme="Unnumbered" +#report_todo="Unnumbered" diff --git a/derive/src/args.rs b/derive/src/args.rs index a6d88db5..b189b29c 100644 --- a/derive/src/args.rs +++ b/derive/src/args.rs @@ -1,8 +1,10 @@ use std::fmt::{self, Display, Formatter}; -use darling::ast::{Data, Fields}; -use darling::util::{Ignored, SpannedValue}; -use darling::{FromDeriveInput, FromField, FromMeta, FromVariant}; +use darling::{ + ast::{Data, Fields}, + util::{Ignored, SpannedValue}, + FromDeriveInput, FromField, FromMeta, FromVariant, +}; use inflector::Inflector; use syn::{ Attribute, Generics, Ident, Lit, LitBool, LitStr, Meta, NestedMeta, Path, Type, Visibility, @@ -186,6 +188,8 @@ pub struct SimpleObject { #[darling(default)] pub name: Option, #[darling(default)] + pub name_type: bool, + #[darling(default)] pub rename_fields: Option, #[darling(default)] pub rename_args: Option, @@ -226,6 +230,7 @@ pub struct Argument { pub struct Object { pub internal: bool, pub name: Option, + pub name_type: bool, pub rename_fields: Option, pub rename_args: Option, pub cache_control: CacheControl, diff --git a/derive/src/complex_object.rs b/derive/src/complex_object.rs index 51b980be..ae35124c 100644 --- a/derive/src/complex_object.rs +++ b/derive/src/complex_object.rs @@ -1,20 +1,21 @@ +use std::{iter::FromIterator, str::FromStr}; + use proc_macro::TokenStream; use proc_macro2::Ident; use quote::quote; -use std::iter::FromIterator; -use std::str::FromStr; -use syn::ext::IdentExt; use syn::{ - punctuated::Punctuated, Block, Error, FnArg, ImplItem, ItemImpl, Pat, ReturnType, Token, Type, - TypeReference, + ext::IdentExt, punctuated::Punctuated, Block, Error, FnArg, ImplItem, ItemImpl, Pat, + ReturnType, Token, Type, TypeReference, }; -use crate::args::{self, ComplexityType, RenameRuleExt, RenameTarget}; -use crate::output_type::OutputType; -use crate::utils::{ - extract_input_args, gen_deprecation, generate_default, generate_guards, get_cfg_attrs, - get_crate_name, get_rustdoc, get_type_path_and_name, parse_complexity_expr, - parse_graphql_attrs, remove_graphql_attrs, visible_fn, GeneratorResult, +use crate::{ + args::{self, ComplexityType, RenameRuleExt, RenameTarget}, + output_type::OutputType, + utils::{ + extract_input_args, gen_deprecation, generate_default, generate_guards, get_cfg_attrs, + get_crate_name, get_rustdoc, get_type_path_and_name, parse_complexity_expr, + parse_graphql_attrs, remove_graphql_attrs, visible_fn, GeneratorResult, + }, }; pub fn generate( diff --git a/derive/src/description.rs b/derive/src/description.rs index 0d049dcd..26543928 100644 --- a/derive/src/description.rs +++ b/derive/src/description.rs @@ -1,8 +1,10 @@ use proc_macro::TokenStream; use quote::quote; -use crate::args; -use crate::utils::{get_crate_name, get_rustdoc, GeneratorResult}; +use crate::{ + args, + utils::{get_crate_name, get_rustdoc, GeneratorResult}, +}; pub fn generate(desc_args: &args::Description) -> GeneratorResult { let crate_name = get_crate_name(desc_args.internal); diff --git a/derive/src/directive.rs b/derive/src/directive.rs index 322b7037..b0f79239 100644 --- a/derive/src/directive.rs +++ b/derive/src/directive.rs @@ -1,13 +1,14 @@ use proc_macro::TokenStream; use quote::quote; -use syn::ext::IdentExt; -use syn::{Error, FnArg, ItemFn, Pat}; +use syn::{ext::IdentExt, Error, FnArg, ItemFn, Pat}; -use crate::args; -use crate::args::{Argument, RenameRuleExt, RenameTarget}; -use crate::utils::{ - generate_default, get_crate_name, get_rustdoc, parse_graphql_attrs, remove_graphql_attrs, - visible_fn, GeneratorResult, +use crate::{ + args, + args::{Argument, RenameRuleExt, RenameTarget}, + utils::{ + generate_default, get_crate_name, get_rustdoc, parse_graphql_attrs, remove_graphql_attrs, + visible_fn, GeneratorResult, + }, }; pub fn generate( diff --git a/derive/src/enum.rs b/derive/src/enum.rs index ea22520f..433aa35e 100644 --- a/derive/src/enum.rs +++ b/derive/src/enum.rs @@ -1,11 +1,12 @@ use darling::ast::Data; use proc_macro::TokenStream; use quote::quote; -use syn::ext::IdentExt; -use syn::Error; +use syn::{ext::IdentExt, Error}; -use crate::args::{self, RenameRuleExt, RenameTarget}; -use crate::utils::{gen_deprecation, get_crate_name, get_rustdoc, visible_fn, GeneratorResult}; +use crate::{ + args::{self, RenameRuleExt, RenameTarget}, + utils::{gen_deprecation, get_crate_name, get_rustdoc, visible_fn, GeneratorResult}, +}; pub fn generate(enum_args: &args::Enum) -> GeneratorResult { let crate_name = get_crate_name(enum_args.internal); diff --git a/derive/src/input_object.rs b/derive/src/input_object.rs index a02aecda..7ca49f15 100644 --- a/derive/src/input_object.rs +++ b/derive/src/input_object.rs @@ -1,11 +1,12 @@ use darling::ast::Data; use proc_macro::TokenStream; use quote::quote; -use syn::ext::IdentExt; -use syn::Error; +use syn::{ext::IdentExt, Error}; -use crate::args::{self, RenameRuleExt, RenameTarget}; -use crate::utils::{generate_default, get_crate_name, get_rustdoc, visible_fn, GeneratorResult}; +use crate::{ + args::{self, RenameRuleExt, RenameTarget}, + utils::{generate_default, get_crate_name, get_rustdoc, visible_fn, GeneratorResult}, +}; pub fn generate(object_args: &args::InputObject) -> GeneratorResult { let crate_name = get_crate_name(object_args.internal); diff --git a/derive/src/interface.rs b/derive/src/interface.rs index 0bdda0e0..a40107bf 100644 --- a/derive/src/interface.rs +++ b/derive/src/interface.rs @@ -4,14 +4,15 @@ use darling::ast::{Data, Style}; use proc_macro::TokenStream; use proc_macro2::{Ident, Span}; use quote::quote; -use syn::visit_mut::VisitMut; -use syn::{Error, Type}; +use syn::{visit_mut::VisitMut, Error, Type}; -use crate::args::{self, InterfaceField, InterfaceFieldArgument, RenameRuleExt, RenameTarget}; -use crate::output_type::OutputType; -use crate::utils::{ - gen_deprecation, generate_default, get_crate_name, get_rustdoc, visible_fn, GeneratorResult, - RemoveLifetime, +use crate::{ + args::{self, InterfaceField, InterfaceFieldArgument, RenameRuleExt, RenameTarget}, + output_type::OutputType, + utils::{ + gen_deprecation, generate_default, get_crate_name, get_rustdoc, visible_fn, + GeneratorResult, RemoveLifetime, + }, }; pub fn generate(interface_args: &args::Interface) -> GeneratorResult { diff --git a/derive/src/lib.rs b/derive/src/lib.rs index f9db55c3..45541b51 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -26,8 +26,7 @@ mod validators; use darling::{FromDeriveInput, FromMeta}; use proc_macro::TokenStream; -use syn::parse_macro_input; -use syn::{AttributeArgs, DeriveInput, ItemFn, ItemImpl}; +use syn::{parse_macro_input, AttributeArgs, DeriveInput, ItemFn, ItemImpl}; #[proc_macro_attribute] #[allow(non_snake_case)] diff --git a/derive/src/merged_object.rs b/derive/src/merged_object.rs index 362f2a71..e0ee880e 100644 --- a/derive/src/merged_object.rs +++ b/derive/src/merged_object.rs @@ -4,8 +4,10 @@ use proc_macro2::Span; use quote::quote; use syn::{Error, LitInt}; -use crate::args::{self, RenameTarget}; -use crate::utils::{get_crate_name, get_rustdoc, visible_fn, GeneratorResult}; +use crate::{ + args::{self, RenameTarget}, + utils::{get_crate_name, get_rustdoc, visible_fn, GeneratorResult}, +}; pub fn generate(object_args: &args::MergedObject) -> GeneratorResult { let crate_name = get_crate_name(object_args.internal); diff --git a/derive/src/merged_subscription.rs b/derive/src/merged_subscription.rs index d1038653..6dd3e5e0 100644 --- a/derive/src/merged_subscription.rs +++ b/derive/src/merged_subscription.rs @@ -4,8 +4,10 @@ use proc_macro2::Span; use quote::quote; use syn::{Error, LitInt}; -use crate::args::{self, RenameTarget}; -use crate::utils::{get_crate_name, get_rustdoc, visible_fn, GeneratorResult}; +use crate::{ + args::{self, RenameTarget}, + utils::{get_crate_name, get_rustdoc, visible_fn, GeneratorResult}, +}; pub fn generate(object_args: &args::MergedSubscription) -> GeneratorResult { let crate_name = get_crate_name(object_args.internal); diff --git a/derive/src/newtype.rs b/derive/src/newtype.rs index 7113c1b9..afeabc51 100644 --- a/derive/src/newtype.rs +++ b/derive/src/newtype.rs @@ -3,8 +3,10 @@ use proc_macro::TokenStream; use quote::quote; use syn::Error; -use crate::args::{self, NewTypeName, RenameTarget}; -use crate::utils::{get_crate_name, get_rustdoc, visible_fn, GeneratorResult}; +use crate::{ + args::{self, NewTypeName, RenameTarget}, + utils::{get_crate_name, get_rustdoc, visible_fn, GeneratorResult}, +}; pub fn generate(newtype_args: &args::NewType) -> GeneratorResult { let crate_name = get_crate_name(newtype_args.internal); diff --git a/derive/src/object.rs b/derive/src/object.rs index 5326f1d8..1a653cf4 100644 --- a/derive/src/object.rs +++ b/derive/src/object.rs @@ -1,20 +1,21 @@ +use std::{iter::FromIterator, str::FromStr}; + use proc_macro::TokenStream; use proc_macro2::Ident; use quote::quote; -use std::iter::FromIterator; -use std::str::FromStr; -use syn::ext::IdentExt; use syn::{ - punctuated::Punctuated, Block, Error, FnArg, ImplItem, ItemImpl, Pat, ReturnType, Token, Type, - TypeReference, + ext::IdentExt, punctuated::Punctuated, Block, Error, FnArg, ImplItem, ItemImpl, Pat, + ReturnType, Token, Type, TypeReference, }; -use crate::args::{self, ComplexityType, RenameRuleExt, RenameTarget}; -use crate::output_type::OutputType; -use crate::utils::{ - extract_input_args, gen_deprecation, generate_default, generate_guards, get_cfg_attrs, - get_crate_name, get_rustdoc, get_type_path_and_name, parse_complexity_expr, - parse_graphql_attrs, remove_graphql_attrs, visible_fn, GeneratorResult, +use crate::{ + args::{self, ComplexityType, RenameRuleExt, RenameTarget}, + output_type::OutputType, + utils::{ + extract_input_args, gen_deprecation, generate_default, generate_guards, get_cfg_attrs, + get_crate_name, get_rustdoc, get_type_path_and_name, parse_complexity_expr, + parse_graphql_attrs, remove_graphql_attrs, visible_fn, GeneratorResult, + }, }; pub fn generate( @@ -25,10 +26,18 @@ pub fn generate( let (self_ty, self_name) = get_type_path_and_name(item_impl.self_ty.as_ref())?; let (impl_generics, _, where_clause) = item_impl.generics.split_for_impl(); let extends = object_args.extends; - let gql_typename = object_args - .name - .clone() - .unwrap_or_else(|| RenameTarget::Type.rename(self_name.clone())); + let gql_typename = if !object_args.name_type { + object_args + .name + .as_ref() + .map(|name| quote!(::std::borrow::Cow::Borrowed(#name))) + .unwrap_or_else(|| { + let name = RenameTarget::Type.rename(self_name.clone()); + quote!(::std::borrow::Cow::Borrowed(#name)) + }) + } else { + quote!(::type_name()) + }; let desc = if object_args.use_type_description { quote! { ::std::option::Option::Some(::description()) } @@ -286,7 +295,6 @@ pub fn generate( let ident = &method.sig.ident; schema_fields.push(quote! { - #crate_name::static_assertions::assert_impl_one!(#ty: #crate_name::ObjectType); <#ty>::create_type_info(registry); if let #crate_name::registry::MetaType::Object { fields: obj_fields, .. } = registry.create_fake_output_type::<#ty>() { @@ -681,12 +689,12 @@ pub fn generate( #[#crate_name::async_trait::async_trait] impl #impl_generics #crate_name::OutputType for #self_ty #where_clause { fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> { - ::std::borrow::Cow::Borrowed(#gql_typename) + #gql_typename } fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String { let ty = registry.create_output_type::(#crate_name::registry::MetaTypeId::Object, |registry| #crate_name::registry::MetaType::Object { - name: ::std::borrow::ToOwned::to_owned(#gql_typename), + name: ::std::borrow::Cow::into_owned(#gql_typename), description: #desc, fields: { let mut fields = #crate_name::indexmap::IndexMap::new(); diff --git a/derive/src/oneof_object.rs b/derive/src/oneof_object.rs index 330b6e7d..12a70ac9 100644 --- a/derive/src/oneof_object.rs +++ b/derive/src/oneof_object.rs @@ -1,12 +1,15 @@ +use std::collections::HashSet; + use darling::ast::{Data, Style}; use proc_macro::TokenStream; use quote::quote; -use std::collections::HashSet; use syn::{Error, Type}; -use crate::args; -use crate::args::{RenameRuleExt, RenameTarget}; -use crate::utils::{get_crate_name, get_rustdoc, visible_fn, GeneratorResult}; +use crate::{ + args, + args::{RenameRuleExt, RenameTarget}, + utils::{get_crate_name, get_rustdoc, visible_fn, GeneratorResult}, +}; pub fn generate(object_args: &args::OneofObject) -> GeneratorResult { let crate_name = get_crate_name(object_args.internal); diff --git a/derive/src/scalar.rs b/derive/src/scalar.rs index a4838f98..a8f99a18 100644 --- a/derive/src/scalar.rs +++ b/derive/src/scalar.rs @@ -2,9 +2,9 @@ use proc_macro::TokenStream; use quote::quote; use syn::ItemImpl; -use crate::args::{self, RenameTarget}; -use crate::utils::{ - get_crate_name, get_rustdoc, get_type_path_and_name, visible_fn, GeneratorResult, +use crate::{ + args::{self, RenameTarget}, + utils::{get_crate_name, get_rustdoc, get_type_path_and_name, visible_fn, GeneratorResult}, }; pub fn generate( diff --git a/derive/src/simple_object.rs b/derive/src/simple_object.rs index 900c3a75..4d5d60b2 100644 --- a/derive/src/simple_object.rs +++ b/derive/src/simple_object.rs @@ -1,14 +1,15 @@ +use std::str::FromStr; + use darling::ast::Data; use proc_macro::TokenStream; use quote::quote; -use std::str::FromStr; -use syn::ext::IdentExt; -use syn::visit::Visit; -use syn::{Error, Ident, LifetimeDef, Path, Type}; +use syn::{ext::IdentExt, visit::Visit, Error, Ident, LifetimeDef, Path, Type}; -use crate::args::{self, RenameRuleExt, RenameTarget, SimpleObjectField}; -use crate::utils::{ - gen_deprecation, generate_guards, get_crate_name, get_rustdoc, visible_fn, GeneratorResult, +use crate::{ + args::{self, RenameRuleExt, RenameTarget, SimpleObjectField}, + utils::{ + gen_deprecation, generate_guards, get_crate_name, get_rustdoc, visible_fn, GeneratorResult, + }, }; #[derive(Debug)] @@ -29,10 +30,18 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult::type_name()) + }; let desc = get_rustdoc(&object_args.attrs)? .map(|s| quote! { ::std::option::Option::Some(#s) }) @@ -172,7 +181,6 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult() { @@ -307,12 +315,12 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult ::std::borrow::Cow<'static, ::std::primitive::str> { - ::std::borrow::Cow::Borrowed(#gql_typename) + #gql_typename } fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String { registry.create_output_type::(#crate_name::registry::MetaTypeId::Object, |registry| #crate_name::registry::MetaType::Object { - name: ::std::borrow::ToOwned::to_owned(#gql_typename), + name: ::std::borrow::Cow::into_owned(#gql_typename), description: #desc, fields: { let mut fields = #crate_name::indexmap::IndexMap::new(); diff --git a/derive/src/subscription.rs b/derive/src/subscription.rs index 77120f36..e9cb41a1 100644 --- a/derive/src/subscription.rs +++ b/derive/src/subscription.rs @@ -1,14 +1,18 @@ use proc_macro::TokenStream; use quote::quote; -use syn::ext::IdentExt; -use syn::{Block, Error, ImplItem, ItemImpl, ReturnType, Type, TypeImplTrait, TypeParamBound}; +use syn::{ + ext::IdentExt, Block, Error, ImplItem, ItemImpl, ReturnType, Type, TypeImplTrait, + TypeParamBound, +}; -use crate::args::{self, ComplexityType, RenameRuleExt, RenameTarget, SubscriptionField}; -use crate::output_type::OutputType; -use crate::utils::{ - extract_input_args, gen_deprecation, generate_default, generate_guards, get_cfg_attrs, - get_crate_name, get_rustdoc, get_type_path_and_name, parse_complexity_expr, - parse_graphql_attrs, remove_graphql_attrs, visible_fn, GeneratorResult, +use crate::{ + args::{self, ComplexityType, RenameRuleExt, RenameTarget, SubscriptionField}, + output_type::OutputType, + utils::{ + extract_input_args, gen_deprecation, generate_default, generate_guards, get_cfg_attrs, + get_crate_name, get_rustdoc, get_type_path_and_name, parse_complexity_expr, + parse_graphql_attrs, remove_graphql_attrs, visible_fn, GeneratorResult, + }, }; pub fn generate( diff --git a/derive/src/union.rs b/derive/src/union.rs index 62c8d074..49df7ff5 100644 --- a/derive/src/union.rs +++ b/derive/src/union.rs @@ -1,12 +1,14 @@ +use std::collections::HashSet; + use darling::ast::{Data, Style}; use proc_macro::TokenStream; use quote::quote; -use std::collections::HashSet; -use syn::visit_mut::VisitMut; -use syn::{Error, Type}; +use syn::{visit_mut::VisitMut, Error, Type}; -use crate::args::{self, RenameTarget}; -use crate::utils::{get_crate_name, get_rustdoc, visible_fn, GeneratorResult, RemoveLifetime}; +use crate::{ + args::{self, RenameTarget}, + utils::{get_crate_name, get_rustdoc, visible_fn, GeneratorResult, RemoveLifetime}, +}; pub fn generate(union_args: &args::Union) -> GeneratorResult { let crate_name = get_crate_name(union_args.internal); diff --git a/derive/src/utils.rs b/derive/src/utils.rs index 871483d8..c11e66a0 100644 --- a/derive/src/utils.rs +++ b/derive/src/utils.rs @@ -1,15 +1,13 @@ use std::collections::HashSet; -use darling::util::SpannedValue; -use darling::FromMeta; +use darling::{util::SpannedValue, FromMeta}; use proc_macro2::{Span, TokenStream, TokenTree}; use proc_macro_crate::{crate_name, FoundCrate}; use quote::quote; -use syn::visit::Visit; -use syn::visit_mut::VisitMut; use syn::{ - visit_mut, Attribute, Error, Expr, ExprPath, FnArg, Ident, ImplItemMethod, Lifetime, Lit, - LitStr, Meta, Pat, PatIdent, Type, TypeGroup, TypeParamBound, TypeReference, + visit::Visit, visit_mut, visit_mut::VisitMut, Attribute, Error, Expr, ExprPath, FnArg, Ident, + ImplItemMethod, Lifetime, Lit, LitStr, Meta, Pat, PatIdent, Type, TypeGroup, TypeParamBound, + TypeReference, }; use thiserror::Error; diff --git a/derive/src/validators.rs b/derive/src/validators.rs index ed50eb28..5d22e2d7 100644 --- a/derive/src/validators.rs +++ b/derive/src/validators.rs @@ -1,5 +1,4 @@ -use darling::util::SpannedValue; -use darling::FromMeta; +use darling::{util::SpannedValue, FromMeta}; use proc_macro2::TokenStream; use quote::{quote, ToTokens}; use syn::{Error, Expr, Lit, Result}; diff --git a/integrations/actix-web/src/request.rs b/integrations/actix-web/src/request.rs index 7ef37232..fbc480ee 100644 --- a/integrations/actix-web/src/request.rs +++ b/integrations/actix-web/src/request.rs @@ -1,22 +1,27 @@ -use actix_http::body::BoxBody; -use actix_web::error::JsonPayloadError; -use std::future::Future; -use std::io::{self, ErrorKind}; -use std::pin::Pin; +use std::{ + future::Future, + io::{self, ErrorKind}, + pin::Pin, +}; -use actix_http::error::PayloadError; -use actix_web::dev::Payload; -use actix_web::http::{Method, StatusCode}; -use actix_web::{http, Error, FromRequest, HttpRequest, HttpResponse, Responder, Result}; -use futures_util::future::{self, FutureExt}; -use futures_util::{StreamExt, TryStreamExt}; - -use async_graphql::http::MultipartOptions; -use async_graphql::ParseRequestError; +use actix_http::{body::BoxBody, error::PayloadError}; +use actix_web::{ + dev::Payload, + error::JsonPayloadError, + http, + http::{Method, StatusCode}, + Error, FromRequest, HttpRequest, HttpResponse, Responder, Result, +}; +use async_graphql::{http::MultipartOptions, ParseRequestError}; +use futures_util::{ + future::{self, FutureExt}, + StreamExt, TryStreamExt, +}; /// Extractor for GraphQL request. /// -/// `async_graphql::http::MultipartOptions` allows to configure extraction process. +/// `async_graphql::http::MultipartOptions` allows to configure extraction +/// process. pub struct GraphQLRequest(pub async_graphql::Request); impl GraphQLRequest { @@ -47,7 +52,8 @@ impl FromRequest for GraphQLRequest { /// Extractor for GraphQL batch request. /// -/// `async_graphql::http::MultipartOptions` allows to configure extraction process. +/// `async_graphql::http::MultipartOptions` allows to configure extraction +/// process. pub struct GraphQLBatchRequest(pub async_graphql::BatchRequest); impl GraphQLBatchRequest { @@ -138,8 +144,8 @@ impl FromRequest for GraphQLBatchRequest { /// Responder for a GraphQL response. /// -/// This contains a batch response, but since regular responses are a type of batch response it -/// works for both. +/// This contains a batch response, but since regular responses are a type of +/// batch response it works for both. pub struct GraphQLResponse(pub async_graphql::BatchResponse); impl From for GraphQLResponse { @@ -156,9 +162,10 @@ impl From for GraphQLResponse { #[cfg(feature = "cbor")] mod cbor { - use actix_web::{http::StatusCode, ResponseError}; use core::fmt; + use actix_web::{http::StatusCode, ResponseError}; + #[derive(Debug)] pub struct Error(pub serde_cbor::Error); impl fmt::Display for Error { diff --git a/integrations/actix-web/src/subscription.rs b/integrations/actix-web/src/subscription.rs index 743e127c..bc419374 100644 --- a/integrations/actix-web/src/subscription.rs +++ b/integrations/actix-web/src/subscription.rs @@ -1,21 +1,21 @@ -use std::future::Future; -use std::str::FromStr; -use std::time::{Duration, Instant}; +use std::{ + future::Future, + str::FromStr, + time::{Duration, Instant}, +}; use actix::{ - Actor, ActorContext, AsyncContext, ContextFutureSpawner, StreamHandler, WrapFuture, WrapStream, + Actor, ActorContext, ActorFutureExt, ActorStreamExt, AsyncContext, ContextFutureSpawner, + StreamHandler, WrapFuture, WrapStream, }; -use actix::{ActorFutureExt, ActorStreamExt}; -use actix_http::error::PayloadError; -use actix_http::ws; -use actix_web::web::Bytes; -use actix_web::{Error, HttpRequest, HttpResponse}; +use actix_http::{error::PayloadError, ws}; +use actix_web::{web::Bytes, Error, HttpRequest, HttpResponse}; use actix_web_actors::ws::{CloseReason, Message, ProtocolError, WebsocketContext}; -use futures_util::future::Ready; -use futures_util::stream::Stream; - -use async_graphql::http::{WebSocket, WebSocketProtocols, WsMessage, ALL_WEBSOCKET_PROTOCOLS}; -use async_graphql::{Data, ObjectType, Result, Schema, SubscriptionType}; +use async_graphql::{ + http::{WebSocket, WebSocketProtocols, WsMessage, ALL_WEBSOCKET_PROTOCOLS}, + Data, ObjectType, Result, Schema, SubscriptionType, +}; +use futures_util::{future::Ready, stream::Stream}; const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5); const CLIENT_TIMEOUT: Duration = Duration::from_secs(10); @@ -63,17 +63,19 @@ where OnInit: Fn(serde_json::Value) -> OnInitFut + Unpin + Send + 'static, OnInitFut: Future> + Send + 'static, { - /// Specify the initial subscription context data, usually you can get something from the - /// incoming request to create it. + /// Specify the initial subscription context data, usually you can get + /// something from the incoming request to create it. #[must_use] pub fn with_data(self, data: Data) -> Self { Self { data, ..self } } - /// Specify a callback function to be called when the connection is initialized. + /// Specify a callback function to be called when the connection is + /// initialized. /// /// You can get something from the payload of [`GQL_CONNECTION_INIT` message](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_connection_init) to create [`Data`]. - /// The data returned by this callback function will be merged with the data specified by [`with_data`]. + /// The data returned by this callback function will be merged with the data + /// specified by [`with_data`]. pub fn on_connection_init( self, callback: OnConnInit2, diff --git a/integrations/actix-web/tests/graphql.rs b/integrations/actix-web/tests/graphql.rs index 3f5c9690..02ce42ae 100644 --- a/integrations/actix-web/tests/graphql.rs +++ b/integrations/actix-web/tests/graphql.rs @@ -1,9 +1,7 @@ use actix_http::Method; -use actix_web::dev::Service; -use actix_web::{guard, test, web, web::Data, App}; -use serde_json::json; - +use actix_web::{dev::Service, guard, test, web, web::Data, App}; use async_graphql::*; +use serde_json::json; use test_utils::*; mod test_utils; diff --git a/integrations/actix-web/tests/test_utils.rs b/integrations/actix-web/tests/test_utils.rs index f9b4c539..e4f89da5 100644 --- a/integrations/actix-web/tests/test_utils.rs +++ b/integrations/actix-web/tests/test_utils.rs @@ -1,6 +1,6 @@ use actix_web::{web, HttpRequest, HttpResponse}; -use async_graphql::http::{playground_source, GraphQLPlaygroundConfig}; use async_graphql::{ + http::{playground_source, GraphQLPlaygroundConfig}, Context, EmptyMutation, EmptySubscription, Object, ObjectType, Schema, SubscriptionType, }; use async_graphql_actix_web::{GraphQLRequest, GraphQLResponse}; diff --git a/integrations/axum/src/extract.rs b/integrations/axum/src/extract.rs index df298cfa..e5e54201 100644 --- a/integrations/axum/src/extract.rs +++ b/integrations/axum/src/extract.rs @@ -1,12 +1,11 @@ use std::io::ErrorKind; -use async_graphql::futures_util::TryStreamExt; -use async_graphql::http::MultipartOptions; -use async_graphql::ParseRequestError; -use axum::http::Method; +use async_graphql::{futures_util::TryStreamExt, http::MultipartOptions, ParseRequestError}; use axum::{ extract::{BodyStream, FromRequest, RequestParts}, - http, BoxError, + http, + http::Method, + BoxError, }; use bytes::Bytes; use tokio_util::compat::TokioAsyncReadCompatExt; @@ -25,10 +24,12 @@ impl GraphQLRequest { /// Rejection response types. pub mod rejection { use async_graphql::ParseRequestError; - use axum::body::{boxed, Body, BoxBody}; - use axum::http; - use axum::http::StatusCode; - use axum::response::IntoResponse; + use axum::{ + body::{boxed, Body, BoxBody}, + http, + http::StatusCode, + response::IntoResponse, + }; /// Rejection used for [`GraphQLRequest`](GraphQLRequest). pub struct GraphQLRejection(pub ParseRequestError); diff --git a/integrations/axum/src/response.rs b/integrations/axum/src/response.rs index 55308902..010d25ec 100644 --- a/integrations/axum/src/response.rs +++ b/integrations/axum/src/response.rs @@ -1,12 +1,14 @@ -use axum::body::{boxed, Body, BoxBody}; -use axum::http; -use axum::http::{HeaderValue, Response}; -use axum::response::IntoResponse; +use axum::{ + body::{boxed, Body, BoxBody}, + http, + http::{HeaderValue, Response}, + response::IntoResponse, +}; /// Responder for a GraphQL response. /// -/// This contains a batch response, but since regular responses are a type of batch response it -/// works for both. +/// This contains a batch response, but since regular responses are a type of +/// batch response it works for both. pub struct GraphQLResponse(pub async_graphql::BatchResponse); impl From for GraphQLResponse { diff --git a/integrations/axum/src/subscription.rs b/integrations/axum/src/subscription.rs index 9333bb7e..0bf42338 100644 --- a/integrations/axum/src/subscription.rs +++ b/integrations/axum/src/subscription.rs @@ -1,20 +1,26 @@ -use std::borrow::Cow; -use std::convert::Infallible; -use std::future::Future; -use std::str::FromStr; +use std::{borrow::Cow, convert::Infallible, future::Future, str::FromStr}; -use async_graphql::futures_util::task::{Context, Poll}; -use async_graphql::http::{WebSocketProtocols, WsMessage, ALL_WEBSOCKET_PROTOCOLS}; -use async_graphql::{Data, ObjectType, Result, Schema, SubscriptionType}; -use axum::body::{boxed, BoxBody, HttpBody}; -use axum::extract::ws::{CloseFrame, Message}; -use axum::extract::{FromRequest, RequestParts, WebSocketUpgrade}; -use axum::http::{self, Request, Response, StatusCode}; -use axum::response::IntoResponse; -use axum::Error; -use futures_util::future::{BoxFuture, Ready}; -use futures_util::stream::{SplitSink, SplitStream}; -use futures_util::{future, Sink, SinkExt, Stream, StreamExt}; +use async_graphql::{ + futures_util::task::{Context, Poll}, + http::{WebSocketProtocols, WsMessage, ALL_WEBSOCKET_PROTOCOLS}, + Data, ObjectType, Result, Schema, SubscriptionType, +}; +use axum::{ + body::{boxed, BoxBody, HttpBody}, + extract::{ + ws::{CloseFrame, Message}, + FromRequest, RequestParts, WebSocketUpgrade, + }, + http::{self, Request, Response, StatusCode}, + response::IntoResponse, + Error, +}; +use futures_util::{ + future, + future::{BoxFuture, Ready}, + stream::{SplitSink, SplitStream}, + Sink, SinkExt, Stream, StreamExt, +}; use tower_service::Service; /// A GraphQL protocol extractor. @@ -191,17 +197,19 @@ where OnConnInit: Fn(serde_json::Value) -> OnConnInitFut + Send + Sync + 'static, OnConnInitFut: Future> + Send + 'static, { - /// Specify the initial subscription context data, usually you can get something from the - /// incoming request to create it. + /// Specify the initial subscription context data, usually you can get + /// something from the incoming request to create it. #[must_use] pub fn with_data(self, data: Data) -> Self { Self { data, ..self } } - /// Specify a callback function to be called when the connection is initialized. + /// Specify a callback function to be called when the connection is + /// initialized. /// /// You can get something from the payload of [`GQL_CONNECTION_INIT` message](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_connection_init) to create [`Data`]. - /// The data returned by this callback function will be merged with the data specified by [`with_data`]. + /// The data returned by this callback function will be merged with the data + /// specified by [`with_data`]. pub fn on_connection_init( self, callback: OnConnInit2, diff --git a/integrations/poem/src/extractor.rs b/integrations/poem/src/extractor.rs index f1d190d0..4d33a989 100644 --- a/integrations/poem/src/extractor.rs +++ b/integrations/poem/src/extractor.rs @@ -1,23 +1,31 @@ use async_graphql::http::MultipartOptions; -use poem::error::BadRequest; -use poem::http::{header, Method}; -use poem::web::Query; -use poem::{async_trait, FromRequest, Request, RequestBody, Result}; +use poem::{ + async_trait, + error::BadRequest, + http::{header, Method}, + web::Query, + FromRequest, Request, RequestBody, Result, +}; use tokio_util::compat::TokioAsyncReadCompatExt; /// An extractor for GraphQL request. /// -/// You can just use the extractor as in the example below, but I would recommend using -/// the [`GraphQL`](crate::GraphQL) endpoint because it is easier to integrate. +/// You can just use the extractor as in the example below, but I would +/// recommend using the [`GraphQL`](crate::GraphQL) endpoint because it is +/// easier to integrate. /// /// # Example /// /// ``` -/// use poem::{handler, Route, post, EndpointExt}; -/// use poem::web::{Json, Data}; -/// use poem::middleware::AddData; -/// use async_graphql_poem::GraphQLRequest; /// use async_graphql::{EmptyMutation, EmptySubscription, Object, Schema}; +/// use async_graphql_poem::GraphQLRequest; +/// use poem::{ +/// handler, +/// middleware::AddData, +/// post, +/// web::{Data, Json}, +/// EndpointExt, Route, +/// }; /// /// struct Query; /// diff --git a/integrations/poem/src/query.rs b/integrations/poem/src/query.rs index 604d26a0..68230851 100644 --- a/integrations/poem/src/query.rs +++ b/integrations/poem/src/query.rs @@ -8,9 +8,9 @@ use crate::{GraphQLBatchRequest, GraphQLBatchResponse}; /// # Example /// /// ``` -/// use poem::{Route, post}; -/// use async_graphql_poem::GraphQL; /// use async_graphql::{EmptyMutation, EmptySubscription, Object, Schema}; +/// use async_graphql_poem::GraphQL; +/// use poem::{post, Route}; /// /// struct Query; /// diff --git a/integrations/poem/src/response.rs b/integrations/poem/src/response.rs index 538e9a17..efb873e9 100644 --- a/integrations/poem/src/response.rs +++ b/integrations/poem/src/response.rs @@ -1,5 +1,4 @@ -use poem::web::Json; -use poem::{IntoResponse, Response}; +use poem::{web::Json, IntoResponse, Response}; /// Response for `async_graphql::Request`. pub struct GraphQLResponse(pub async_graphql::Response); diff --git a/integrations/poem/src/subscription.rs b/integrations/poem/src/subscription.rs index df58af18..be87f65f 100644 --- a/integrations/poem/src/subscription.rs +++ b/integrations/poem/src/subscription.rs @@ -1,15 +1,19 @@ -use std::io::Error as IoError; -use std::str::FromStr; +use std::{io::Error as IoError, str::FromStr}; -use async_graphql::http::{WebSocketProtocols, WsMessage, ALL_WEBSOCKET_PROTOCOLS}; -use async_graphql::{Data, ObjectType, Schema, SubscriptionType}; -use futures_util::future::{self, Ready}; -use futures_util::stream::{SplitSink, SplitStream}; -use futures_util::{Future, Sink, SinkExt, Stream, StreamExt}; -use poem::http::StatusCode; -use poem::web::websocket::{Message, WebSocket}; +use async_graphql::{ + http::{WebSocketProtocols, WsMessage, ALL_WEBSOCKET_PROTOCOLS}, + Data, ObjectType, Schema, SubscriptionType, +}; +use futures_util::{ + future::{self, Ready}, + stream::{SplitSink, SplitStream}, + Future, Sink, SinkExt, Stream, StreamExt, +}; use poem::{ - http, Endpoint, Error, FromRequest, IntoResponse, Request, RequestBody, Response, Result, + http, + http::StatusCode, + web::websocket::{Message, WebSocket}, + Endpoint, Error, FromRequest, IntoResponse, Request, RequestBody, Response, Result, }; /// A GraphQL protocol extractor. @@ -39,10 +43,10 @@ impl<'a> FromRequest<'a> for GraphQLProtocol { /// # Example /// /// ``` -/// use poem::{Route, get}; -/// use async_graphql_poem::GraphQLSubscription; /// use async_graphql::{EmptyMutation, Object, Schema, Subscription}; -/// use futures_util::{Stream, stream}; +/// use async_graphql_poem::GraphQLSubscription; +/// use futures_util::{stream, Stream}; +/// use poem::{get, Route}; /// /// struct Query; /// @@ -181,17 +185,19 @@ where OnConnInit: Fn(serde_json::Value) -> OnConnInitFut + Send + Sync + 'static, OnConnInitFut: Future> + Send + 'static, { - /// Specify the initial subscription context data, usually you can get something from the - /// incoming request to create it. + /// Specify the initial subscription context data, usually you can get + /// something from the incoming request to create it. #[must_use] pub fn with_data(self, data: Data) -> Self { Self { data, ..self } } - /// Specify a callback function to be called when the connection is initialized. + /// Specify a callback function to be called when the connection is + /// initialized. /// /// You can get something from the payload of [`GQL_CONNECTION_INIT` message](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_connection_init) to create [`Data`]. - /// The data returned by this callback function will be merged with the data specified by [`with_data`]. + /// The data returned by this callback function will be merged with the data + /// specified by [`with_data`]. pub fn on_connection_init( self, callback: OnConnInit2, diff --git a/integrations/rocket/src/lib.rs b/integrations/rocket/src/lib.rs index aaa651b5..d8dad1ea 100644 --- a/integrations/rocket/src/lib.rs +++ b/integrations/rocket/src/lib.rs @@ -1,10 +1,11 @@ //! Async-graphql integration with Rocket. //! -//! Note: This integrates with the unreleased version 0.5 of Rocket, and so breaking changes in -//! both this library and Rocket are to be expected. +//! Note: This integrates with the unreleased version 0.5 of Rocket, and so +//! breaking changes in both this library and Rocket are to be expected. //! -//! To configure options for sending and receiving multipart requests, add your instance of -//! `MultipartOptions` to the state managed by Rocket (`.manage(your_multipart_options)`). +//! To configure options for sending and receiving multipart requests, add your +//! instance of `MultipartOptions` to the state managed by Rocket +//! (`.manage(your_multipart_options)`). //! //! **[Full Example]()** @@ -14,8 +15,9 @@ use core::any::Any; use std::io::Cursor; -use async_graphql::http::MultipartOptions; -use async_graphql::{ObjectType, ParseRequestError, Schema, SubscriptionType}; +use async_graphql::{ + http::MultipartOptions, ObjectType, ParseRequestError, Schema, SubscriptionType, +}; use rocket::{ data::{self, Data, FromData, ToByteUnit}, form::FromForm, @@ -185,11 +187,11 @@ impl<'r> FromData<'r> for GraphQLRequest { } } -/// Wrapper around `async-graphql::Response` that is a Rocket responder so it can be returned from -/// a routing function in Rocket. +/// Wrapper around `async-graphql::Response` that is a Rocket responder so it +/// can be returned from a routing function in Rocket. /// -/// It contains a `BatchResponse` but since a response is a type of batch response it works for -/// both. +/// It contains a `BatchResponse` but since a response is a type of batch +/// response it works for both. #[derive(Debug)] pub struct GraphQLResponse(pub async_graphql::BatchResponse); diff --git a/integrations/tide/src/lib.rs b/integrations/tide/src/lib.rs index a93621f6..a180374e 100644 --- a/integrations/tide/src/lib.rs +++ b/integrations/tide/src/lib.rs @@ -11,20 +11,20 @@ #[cfg(feature = "websocket")] mod subscription; -use async_graphql::http::MultipartOptions; -use async_graphql::{ObjectType, ParseRequestError, Schema, SubscriptionType}; -use tide::utils::async_trait; +use async_graphql::{ + http::MultipartOptions, ObjectType, ParseRequestError, Schema, SubscriptionType, +}; +#[cfg(feature = "websocket")] +pub use subscription::GraphQLSubscription; use tide::{ http::{ headers::{self, HeaderValue}, Method, }, + utils::async_trait, Body, Request, Response, StatusCode, }; -#[cfg(feature = "websocket")] -pub use subscription::GraphQLSubscription; - /// Create a new GraphQL endpoint with the schema. /// /// Default multipart options are used and batch operations are supported. @@ -106,7 +106,8 @@ pub async fn receive_request( receive_request_opts(request, Default::default()).await } -/// Convert a Tide request to a GraphQL request with options on how to receive multipart. +/// Convert a Tide request to a GraphQL request with options on how to receive +/// multipart. pub async fn receive_request_opts( request: Request, opts: MultipartOptions, @@ -124,7 +125,8 @@ pub async fn receive_batch_request( receive_batch_request_opts(request, Default::default()).await } -/// Convert a Tide request to a GraphQL batch request with options on how to receive multipart. +/// Convert a Tide request to a GraphQL batch request with options on how to +/// receive multipart. pub async fn receive_batch_request_opts( mut request: Request, opts: MultipartOptions, diff --git a/integrations/tide/src/subscription.rs b/integrations/tide/src/subscription.rs index 47de7ddb..547e8df3 100644 --- a/integrations/tide/src/subscription.rs +++ b/integrations/tide/src/subscription.rs @@ -1,15 +1,12 @@ -use std::future::Future; -use std::str::FromStr; +use std::{future::Future, str::FromStr}; -use async_graphql::http::{ - WebSocket as AGWebSocket, WebSocketProtocols, WsMessage, ALL_WEBSOCKET_PROTOCOLS, +use async_graphql::{ + http::{WebSocket as AGWebSocket, WebSocketProtocols, WsMessage, ALL_WEBSOCKET_PROTOCOLS}, + Data, ObjectType, Result, Schema, SubscriptionType, }; -use async_graphql::{Data, ObjectType, Result, Schema, SubscriptionType}; -use futures_util::future::Ready; -use futures_util::{future, StreamExt}; +use futures_util::{future, future::Ready, StreamExt}; use tide::Endpoint; -use tide_websockets::tungstenite::protocol::CloseFrame; -use tide_websockets::Message; +use tide_websockets::{tungstenite::protocol::CloseFrame, Message}; /// A GraphQL subscription endpoint builder. #[cfg_attr(docsrs, doc(cfg(feature = "websocket")))] @@ -49,10 +46,12 @@ where OnConnInit: Fn(serde_json::Value) -> OnConnInitFut + Clone + Send + Sync + 'static, OnConnInitFut: Future> + Send + 'static, { - /// Specify a callback function to be called when the connection is initialized. + /// Specify a callback function to be called when the connection is + /// initialized. /// /// You can get something from the payload of [`GQL_CONNECTION_INIT` message](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_connection_init) to create [`Data`]. - /// The data returned by this callback function will be merged with the data specified by [`with_data`]. + /// The data returned by this callback function will be merged with the data + /// specified by [`with_data`]. pub fn on_connection_init( self, callback: OnConnInit2, diff --git a/integrations/tide/tests/test_utils.rs b/integrations/tide/tests/test_utils.rs index 5d0e2a2b..2cf2bf14 100644 --- a/integrations/tide/tests/test_utils.rs +++ b/integrations/tide/tests/test_utils.rs @@ -1,6 +1,7 @@ -use reqwest::Client; use std::time::Duration; +use reqwest::Client; + pub fn client() -> Client { Client::builder().no_proxy().build().unwrap() } diff --git a/integrations/warp/src/batch_request.rs b/integrations/warp/src/batch_request.rs index 0eb2afa9..a619bd1f 100644 --- a/integrations/warp/src/batch_request.rs +++ b/integrations/warp/src/batch_request.rs @@ -1,17 +1,15 @@ -use std::io; -use std::io::ErrorKind; +use std::{io, io::ErrorKind}; -use async_graphql::http::MultipartOptions; -use async_graphql::{BatchRequest, ObjectType, Schema, SubscriptionType}; +use async_graphql::{http::MultipartOptions, BatchRequest, ObjectType, Schema, SubscriptionType}; use futures_util::TryStreamExt; -use warp::reply::Response as WarpResponse; -use warp::{Buf, Filter, Rejection, Reply}; +use warp::{reply::Response as WarpResponse, Buf, Filter, Rejection, Reply}; use crate::GraphQLBadRequest; /// GraphQL batch request filter /// -/// It outputs a tuple containing the `async_graphql::Schema` and `async_graphql::BatchRequest`. +/// It outputs a tuple containing the `async_graphql::Schema` and +/// `async_graphql::BatchRequest`. pub fn graphql_batch( schema: Schema, ) -> impl Filter, BatchRequest),), Error = Rejection> @@ -24,7 +22,8 @@ where graphql_batch_opts(schema, Default::default()) } -/// Similar to graphql_batch, but you can set the options with :`async_graphql::MultipartOptions`. +/// Similar to graphql_batch, but you can set the options with +/// :`async_graphql::MultipartOptions`. pub fn graphql_batch_opts( schema: Schema, opts: MultipartOptions, diff --git a/integrations/warp/src/error.rs b/integrations/warp/src/error.rs index d505559e..a2b0c44d 100644 --- a/integrations/warp/src/error.rs +++ b/integrations/warp/src/error.rs @@ -1,16 +1,21 @@ -use std::error::Error; -use std::fmt::{self, Display, Formatter}; +use std::{ + error::Error, + fmt::{self, Display, Formatter}, +}; use async_graphql::ParseRequestError; -use warp::http::{Response, StatusCode}; -use warp::hyper::Body; -use warp::reject::Reject; -use warp::Reply; +use warp::{ + http::{Response, StatusCode}, + hyper::Body, + reject::Reject, + Reply, +}; /// Bad request error. /// -/// It's a wrapper of `async_graphql::ParseRequestError`. It is also a `Reply` - by default it just -/// returns a response containing the error message in plain text. +/// It's a wrapper of `async_graphql::ParseRequestError`. It is also a `Reply` - +/// by default it just returns a response containing the error message in plain +/// text. #[derive(Debug)] pub struct GraphQLBadRequest(pub ParseRequestError); diff --git a/integrations/warp/src/request.rs b/integrations/warp/src/request.rs index 882a8b00..79c26325 100644 --- a/integrations/warp/src/request.rs +++ b/integrations/warp/src/request.rs @@ -1,24 +1,25 @@ -use async_graphql::http::MultipartOptions; -use async_graphql::{BatchRequest, ObjectType, Request, Schema, SubscriptionType}; -use warp::reply::Response as WarpResponse; -use warp::{Filter, Rejection, Reply}; +use async_graphql::{ + http::MultipartOptions, BatchRequest, ObjectType, Request, Schema, SubscriptionType, +}; +use warp::{reply::Response as WarpResponse, Filter, Rejection, Reply}; use crate::{graphql_batch_opts, GraphQLBadRequest, GraphQLBatchResponse}; /// GraphQL request filter /// -/// It outputs a tuple containing the `async_graphql::Schema` and `async_graphql::Request`. +/// It outputs a tuple containing the `async_graphql::Schema` and +/// `async_graphql::Request`. /// /// # Examples /// /// *[Full Example]()* /// /// ```no_run +/// use std::convert::Infallible; /// /// use async_graphql::*; /// use async_graphql_warp::*; /// use warp::Filter; -/// use std::convert::Infallible; /// /// struct QueryRoot; /// @@ -33,10 +34,13 @@ use crate::{graphql_batch_opts, GraphQLBadRequest, GraphQLBatchResponse}; /// /// # tokio::runtime::Runtime::new().unwrap().block_on(async { /// let schema = Schema::new(QueryRoot, EmptyMutation, EmptySubscription); -/// let filter = async_graphql_warp::graphql(schema) -/// .and_then(|(schema, request): (MySchema, async_graphql::Request)| async move { -/// Ok::<_, Infallible>(async_graphql_warp::GraphQLResponse::from(schema.execute(request).await)) -/// }); +/// let filter = async_graphql_warp::graphql(schema).and_then( +/// |(schema, request): (MySchema, async_graphql::Request)| async move { +/// Ok::<_, Infallible>(async_graphql_warp::GraphQLResponse::from( +/// schema.execute(request).await, +/// )) +/// }, +/// ); /// warp::serve(filter).run(([0, 0, 0, 0], 8000)).await; /// # }); /// ``` @@ -57,7 +61,8 @@ where graphql_opts(schema, Default::default()) } -/// Similar to graphql, but you can set the options `async_graphql::MultipartOptions`. +/// Similar to graphql, but you can set the options +/// `async_graphql::MultipartOptions`. pub fn graphql_opts( schema: Schema, opts: MultipartOptions, diff --git a/integrations/warp/src/subscription.rs b/integrations/warp/src/subscription.rs index 4f9b7d89..a25b4631 100644 --- a/integrations/warp/src/subscription.rs +++ b/integrations/warp/src/subscription.rs @@ -1,25 +1,28 @@ -use std::future::Future; -use std::str::FromStr; +use std::{future::Future, str::FromStr}; -use async_graphql::http::{WebSocketProtocols, WsMessage}; -use async_graphql::{Data, ObjectType, Result, Schema, SubscriptionType}; -use futures_util::future::Ready; -use futures_util::stream::{SplitSink, SplitStream}; -use futures_util::{future, Sink, Stream, StreamExt}; -use warp::filters::ws; -use warp::ws::Message; -use warp::{Error, Filter, Rejection, Reply}; +use async_graphql::{ + http::{WebSocketProtocols, WsMessage}, + Data, ObjectType, Result, Schema, SubscriptionType, +}; +use futures_util::{ + future, + future::Ready, + stream::{SplitSink, SplitStream}, + Sink, Stream, StreamExt, +}; +use warp::{filters::ws, ws::Message, Error, Filter, Rejection, Reply}; /// GraphQL subscription filter /// /// # Examples /// /// ```no_run +/// use std::time::Duration; +/// /// use async_graphql::*; /// use async_graphql_warp::*; -/// use warp::Filter; /// use futures_util::stream::{Stream, StreamExt}; -/// use std::time::Duration; +/// use warp::Filter; /// /// struct QueryRoot; /// @@ -48,8 +51,8 @@ use warp::{Error, Filter, Rejection, Reply}; /// /// # tokio::runtime::Runtime::new().unwrap().block_on(async { /// let schema = Schema::new(QueryRoot, EmptyMutation, SubscriptionRoot); -/// let filter = async_graphql_warp::graphql_subscription(schema) -/// .or(warp::any().map(|| "Hello, World!")); +/// let filter = +/// async_graphql_warp::graphql_subscription(schema).or(warp::any().map(|| "Hello, World!")); /// warp::serve(filter).run(([0, 0, 0, 0], 8000)).await; /// # }); /// ``` @@ -80,7 +83,8 @@ where }) } -/// Create a `Filter` that parse [WebSocketProtocols] from `sec-websocket-protocol` header. +/// Create a `Filter` that parse [WebSocketProtocols] from +/// `sec-websocket-protocol` header. pub fn graphql_protocol() -> impl Filter + Clone { warp::header::optional::("sec-websocket-protocol").map(|protocols: Option| { @@ -105,11 +109,12 @@ fn default_on_connection_init(_: serde_json::Value) -> Ready Ready OnConnInitFut + Send + Sync + 'static, OnConnInitFut: Future> + Send + 'static, { - /// Specify the initial subscription context data, usually you can get something from the - /// incoming request to create it. + /// Specify the initial subscription context data, usually you can get + /// something from the incoming request to create it. #[must_use] pub fn with_data(self, data: Data) -> Self { Self { data, ..self } } - /// Specify a callback function to be called when the connection is initialized. + /// Specify a callback function to be called when the connection is + /// initialized. /// /// You can get something from the payload of [`GQL_CONNECTION_INIT` message](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_connection_init) to create [`Data`]. - /// The data returned by this callback function will be merged with the data specified by [`with_data`]. + /// The data returned by this callback function will be merged with the data + /// specified by [`with_data`]. pub fn on_connection_init( self, callback: OnConnInit2, diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 13339e95..cb1da95f 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -9,15 +9,15 @@ #![allow(clippy::needless_question_mark)] #![forbid(unsafe_code)] -use crate::types::OperationType; -use async_graphql_value::Name; -use pest::error::LineColLocation; -use pest::RuleType; -use serde::{Serialize, Serializer}; use std::fmt::{self, Display, Formatter}; +use async_graphql_value::Name; pub use parse::{parse_query, parse_schema}; +use pest::{error::LineColLocation, RuleType}; pub use pos::{Pos, Positioned}; +use serde::{Serialize, Serializer}; + +use crate::types::OperationType; pub mod types; diff --git a/parser/src/parse/executable.rs b/parser/src/parse/executable.rs index 6ec0207d..9c8f61dd 100644 --- a/parser/src/parse/executable.rs +++ b/parser/src/parse/executable.rs @@ -1,6 +1,7 @@ -use super::*; use async_graphql_value::Name; +use super::*; + /// Parse a GraphQL query document. /// /// # Errors @@ -399,9 +400,10 @@ fn parse_type_condition( #[cfg(test)] mod tests { - use super::*; use std::fs; + use super::*; + #[test] fn test_parser() { for entry in fs::read_dir("tests/executables").unwrap() { diff --git a/parser/src/parse/mod.rs b/parser/src/parse/mod.rs index 5a584764..a4239145 100644 --- a/parser/src/parse/mod.rs +++ b/parser/src/parse/mod.rs @@ -2,15 +2,21 @@ //! //! This module's structure mirrors `types`. -use crate::pos::{PositionCalculator, Positioned}; -use crate::types::*; -use crate::{Error, Result}; -use pest::iterators::{Pair, Pairs}; -use pest::Parser; -use pest_derive::Parser; use std::collections::hash_map::{self, HashMap}; + +use pest::{ + iterators::{Pair, Pairs}, + Parser, +}; +use pest_derive::Parser; use utils::*; +use crate::{ + pos::{PositionCalculator, Positioned}, + types::*, + Error, Result, +}; + mod executable; mod service; mod utils; diff --git a/parser/src/parse/service.rs b/parser/src/parse/service.rs index fa71f235..1267556e 100644 --- a/parser/src/parse/service.rs +++ b/parser/src/parse/service.rs @@ -398,9 +398,10 @@ fn parse_input_value_definition( #[cfg(test)] mod tests { - use super::*; use std::fs; + use super::*; + #[test] fn test_parser() { for entry in fs::read_dir("tests/services").unwrap() { diff --git a/parser/src/parse/utils.rs b/parser/src/parse/utils.rs index 3b1e4868..2dac7110 100644 --- a/parser/src/parse/utils.rs +++ b/parser/src/parse/utils.rs @@ -1,6 +1,7 @@ +use pest::iterators::{Pair, Pairs}; + use super::Rule; use crate::Result; -use pest::iterators::{Pair, Pairs}; pub(super) fn next_if_rule<'a>(pairs: &mut Pairs<'a, Rule>, rule: Rule) -> Option> { if pairs.peek().map_or(false, |pair| pair.as_rule() == rule) { diff --git a/parser/src/pos.rs b/parser/src/pos.rs index a52b062f..ebe64b50 100644 --- a/parser/src/pos.rs +++ b/parser/src/pos.rs @@ -1,11 +1,13 @@ -use pest::iterators::Pair; -use pest::RuleType; +use std::{ + borrow::{Borrow, BorrowMut}, + cmp::Ordering, + fmt, + hash::{Hash, Hasher}, + str::Chars, +}; + +use pest::{iterators::Pair, RuleType}; use serde::{Deserialize, Serialize}; -use std::borrow::{Borrow, BorrowMut}; -use std::cmp::Ordering; -use std::fmt; -use std::hash::{Hash, Hasher}; -use std::str::Chars; /// Original position of an element in source code. /// @@ -56,8 +58,8 @@ impl Positioned { /// Get the inner node. /// - /// This is most useful in callback chains where `Positioned::into_inner` is easier to read than - /// `|positioned| positioned.node`. + /// This is most useful in callback chains where `Positioned::into_inner` is + /// easier to read than `|positioned| positioned.node`. #[inline] pub fn into_inner(self) -> T { self.node diff --git a/parser/src/types/executable.rs b/parser/src/types/executable.rs index 15afed8b..bf6ef704 100644 --- a/parser/src/types/executable.rs +++ b/parser/src/types/executable.rs @@ -1,8 +1,9 @@ //! Executable document-related GraphQL types. -use super::*; use async_graphql_value::{ConstValue, Name, Value}; +use super::*; + /// An executable GraphQL file or request string. /// /// [Reference](https://spec.graphql.org/October2021/#ExecutableDocument). @@ -36,10 +37,10 @@ impl DocumentOperations { } } -// TODO: This is not implemented as I would like to later implement IntoIterator for -// DocumentOperations (not a reference) without having a breaking change. +// TODO: This is not implemented as I would like to later implement IntoIterator +// for DocumentOperations (not a reference) without having a breaking change. // -//impl<'a> IntoIterator for &'a DocumentOperations { +// impl<'a> IntoIterator for &'a DocumentOperations { // type Item = &'a Positioned; // type IntoIter = OperationsIter<'a>; // @@ -91,7 +92,8 @@ enum OperationsIterInner<'a> { Multiple(hash_map::Iter<'a, Name, Positioned>), } -/// A GraphQL operation, such as `mutation($content:String!) { makePost(content: $content) { id } }`. +/// A GraphQL operation, such as `mutation($content:String!) { makePost(content: +/// $content) { id } }`. /// /// [Reference](https://spec.graphql.org/October2021/#OperationDefinition). #[derive(Debug, Clone)] @@ -106,7 +108,8 @@ pub struct OperationDefinition { pub selection_set: Positioned, } -/// A variable definition inside a list of variable definitions, for example `$name:String!`. +/// A variable definition inside a list of variable definitions, for example +/// `$name:String!`. /// /// [Reference](https://spec.graphql.org/October2021/#VariableDefinition). #[derive(Debug, Clone)] @@ -122,8 +125,8 @@ pub struct VariableDefinition { } impl VariableDefinition { - /// Get the default value of the variable; this is `default_value` if it is present, - /// `Value::Null` if it is nullable and `None` otherwise. + /// Get the default value of the variable; this is `default_value` if it is + /// present, `Value::Null` if it is nullable and `None` otherwise. #[must_use] pub fn default_value(&self) -> Option<&ConstValue> { self.default_value.as_ref().map(|value| &value.node).or({ @@ -145,12 +148,14 @@ pub struct SelectionSet { pub items: Vec>, } -/// A part of an object to be selected; a single field, a fragment spread or an inline fragment. +/// A part of an object to be selected; a single field, a fragment spread or an +/// inline fragment. /// /// [Reference](https://spec.graphql.org/October2021/#Selection). #[derive(Debug, Clone)] pub enum Selection { - /// Select a single field, such as `name` or `weightKilos: weight(unit: KILOGRAMS)`. + /// Select a single field, such as `name` or `weightKilos: weight(unit: + /// KILOGRAMS)`. Field(Positioned), /// Select using a fragment. FragmentSpread(Positioned), @@ -179,7 +184,8 @@ impl Selection { } } -/// A field being selected on an object, such as `name` or `weightKilos: weight(unit: KILOGRAMS)`. +/// A field being selected on an object, such as `name` or `weightKilos: +/// weight(unit: KILOGRAMS)`. /// /// [Reference](https://spec.graphql.org/October2021/#Field). #[derive(Debug, Clone)] @@ -192,13 +198,14 @@ pub struct Field { pub arguments: Vec<(Positioned, Positioned)>, /// The directives in the field selector. pub directives: Vec>, - /// The subfields being selected in this field, if it is an object. Empty if no fields are - /// being selected. + /// The subfields being selected in this field, if it is an object. Empty if + /// no fields are being selected. pub selection_set: Positioned, } impl Field { - /// Get the response key of the field. This is the alias if present and the name otherwise. + /// Get the response key of the field. This is the alias if present and the + /// name otherwise. #[must_use] pub fn response_key(&self) -> &Positioned { self.alias.as_ref().unwrap_or(&self.name) @@ -238,7 +245,8 @@ pub struct InlineFragment { pub selection_set: Positioned, } -/// The definition of a fragment, such as `fragment userFields on User { name age }`. +/// The definition of a fragment, such as `fragment userFields on User { name +/// age }`. /// /// [Reference](https://spec.graphql.org/October2021/#FragmentDefinition). #[derive(Debug, Clone)] diff --git a/parser/src/types/mod.rs b/parser/src/types/mod.rs index 151fa94f..d0cd34d9 100644 --- a/parser/src/types/mod.rs +++ b/parser/src/types/mod.rs @@ -1,22 +1,26 @@ //! GraphQL types. //! -//! The two root types are [`ExecutableDocument`](struct.ExecutableDocument.html) and -//! [`ServiceDocument`](struct.ServiceDocument.html), representing an executable GraphQL query and a -//! GraphQL service respectively. +//! The two root types are +//! [`ExecutableDocument`](struct.ExecutableDocument.html) and +//! [`ServiceDocument`](struct.ServiceDocument.html), representing an executable +//! GraphQL query and a GraphQL service respectively. //! //! This follows the [June 2018 edition of the GraphQL spec](https://spec.graphql.org/October2021/). mod executable; mod service; -use crate::pos::Positioned; -use async_graphql_value::{ConstValue, Name, Value}; -use std::collections::{hash_map, HashMap}; -use std::fmt::{self, Display, Formatter, Write}; +use std::{ + collections::{hash_map, HashMap}, + fmt::{self, Display, Formatter, Write}, +}; +use async_graphql_value::{ConstValue, Name, Value}; pub use executable::*; pub use service::*; +use crate::pos::Positioned; + /// The type of an operation; `query`, `mutation` or `subscription`. /// /// [Reference](https://spec.graphql.org/October2021/#OperationType). @@ -82,8 +86,8 @@ impl Display for Type { } } -/// A GraphQL base type, for example `String` or `[String!]`. This does not include whether the -/// type is nullable; for that see [Type](struct.Type.html). +/// A GraphQL base type, for example `String` or `[String!]`. This does not +/// include whether the type is nullable; for that see [Type](struct.Type.html). #[derive(Debug, PartialEq, Eq, Clone)] pub enum BaseType { /// A named type, such as `String`. @@ -101,9 +105,10 @@ impl Display for BaseType { } } -/// A const GraphQL directive, such as `@deprecated(reason: "Use the other field)`. This differs -/// from [`Directive`](struct.Directive.html) in that it uses [`ConstValue`](enum.ConstValue.html) -/// instead of [`Value`](enum.Value.html). +/// A const GraphQL directive, such as `@deprecated(reason: "Use the other +/// field)`. This differs from [`Directive`](struct.Directive.html) in that it +/// uses [`ConstValue`](enum.ConstValue.html) instead of +/// [`Value`](enum.Value.html). /// /// [Reference](https://spec.graphql.org/October2021/#Directive). #[derive(Debug, Clone)] diff --git a/parser/src/types/service.rs b/parser/src/types/service.rs index f5e2bcdb..57c4e8ba 100644 --- a/parser/src/types/service.rs +++ b/parser/src/types/service.rs @@ -1,8 +1,9 @@ //! Service-related GraphQL types. -use super::*; use async_graphql_value::Name; +use super::*; + /// A GraphQL file or request string defining a GraphQL service. /// /// [Reference](https://spec.graphql.org/October2021/#Document). @@ -52,7 +53,8 @@ pub struct SchemaDefinition { pub struct TypeDefinition { /// Whether the type is an extension of another type. pub extend: bool, - /// The description of the type, if present. This is never present on an extension type. + /// The description of the type, if present. This is never present on an + /// extension type. pub description: Option>, /// The name of the type. pub name: Positioned, @@ -195,11 +197,14 @@ pub struct DirectiveDefinition { /// [Reference](https://spec.graphql.org/October2021/#DirectiveLocation). #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum DirectiveLocation { - /// A [query](enum.OperationType.html#variant.Query) [operation](struct.OperationDefinition.html). + /// A [query](enum.OperationType.html#variant.Query) + /// [operation](struct.OperationDefinition.html). Query, - /// A [mutation](enum.OperationType.html#variant.Mutation) [operation](struct.OperationDefinition.html). + /// A [mutation](enum.OperationType.html#variant.Mutation) + /// [operation](struct.OperationDefinition.html). Mutation, - /// A [subscription](enum.OperationType.html#variant.Subscription) [operation](struct.OperationDefinition.html). + /// A [subscription](enum.OperationType.html#variant.Subscription) + /// [operation](struct.OperationDefinition.html). Subscription, /// A [field](struct.Field.html). Field, @@ -217,8 +222,8 @@ pub enum DirectiveLocation { Object, /// A [field definition](struct.FieldDefinition.html). FieldDefinition, - /// An [input value definition](struct.InputFieldDefinition.html) as the arguments of a field - /// but not an input object. + /// An [input value definition](struct.InputFieldDefinition.html) as the + /// arguments of a field but not an input object. ArgumentDefinition, /// An [interface](struct.InterfaceType.html). Interface, @@ -230,8 +235,8 @@ pub enum DirectiveLocation { EnumValue, /// An [input object](struct.InputObjectType.html). InputObject, - /// An [input value definition](struct.InputValueDefinition.html) on an input object but not a - /// field. + /// An [input value definition](struct.InputValueDefinition.html) on an + /// input object but not a field. InputFieldDefinition, /// An [variable definition](struct.VariableDefinition.html). VariableDefinition, diff --git a/src/base.rs b/src/base.rs index c0e7338e..82335b0e 100644 --- a/src/base.rs +++ b/src/base.rs @@ -1,11 +1,10 @@ -use std::borrow::Cow; -use std::sync::Arc; +use std::{borrow::Cow, sync::Arc}; use async_graphql_value::ConstValue; -use crate::parser::types::Field; -use crate::registry::{self, Registry}; use crate::{ + parser::types::Field, + registry::{self, Registry}, ContainerType, Context, ContextSelectionSet, Error, InputValueError, InputValueResult, Positioned, Result, ServerResult, Value, }; @@ -15,6 +14,12 @@ pub trait Description { fn description() -> &'static str; } +/// Used to specify the GraphQL Type name. +pub trait TypeName: Send + Sync { + /// Returns a GraphQL type name. + fn type_name() -> Cow<'static, str>; +} + /// Represents a GraphQL input type. pub trait InputType: Send + Sync + Sized { /// The raw type used for validator. @@ -67,7 +72,8 @@ pub trait OutputType: Send + Sync { /// Introspection type name /// - /// Is the return value of field `__typename`, the interface and union should return the current type, and the others return `Type::type_name`. + /// Is the return value of field `__typename`, the interface and union + /// should return the current type, and the others return `Type::type_name`. fn introspection_type_name(&self) -> Cow<'static, str> { Self::type_name() } diff --git a/src/context.rs b/src/context.rs index c1bfc1dd..5d318e36 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,24 +1,30 @@ //! Query context. -use std::any::{Any, TypeId}; -use std::collections::HashMap; -use std::fmt::{self, Debug, Display, Formatter}; -use std::ops::Deref; -use std::sync::{Arc, Mutex}; +use std::{ + any::{Any, TypeId}, + collections::HashMap, + fmt::{self, Debug, Display, Formatter}, + ops::Deref, + sync::{Arc, Mutex}, +}; use async_graphql_value::{Value as InputValue, Variables}; use fnv::FnvHashMap; -use http::header::{AsHeaderName, HeaderMap, IntoHeaderName}; -use http::HeaderValue; -use serde::ser::{SerializeSeq, Serializer}; -use serde::Serialize; - -use crate::parser::types::{ - Directive, Field, FragmentDefinition, OperationDefinition, Selection, SelectionSet, +use http::{ + header::{AsHeaderName, HeaderMap, IntoHeaderName}, + HeaderValue, }; -use crate::schema::SchemaEnv; -use crate::{extensions::Extensions, schema::IntrospectionMode}; +use serde::{ + ser::{SerializeSeq, Serializer}, + Serialize, +}; + use crate::{ + extensions::Extensions, + parser::types::{ + Directive, Field, FragmentDefinition, OperationDefinition, Selection, SelectionSet, + }, + schema::{IntrospectionMode, SchemaEnv}, Error, InputType, Lookahead, Name, OneofObjectType, PathSegment, Pos, Positioned, Result, ServerError, ServerResult, UploadValue, Value, }; @@ -27,7 +33,8 @@ use crate::{ pub trait DataContext<'a> { /// Gets the global data defined in the `Context` or `Schema`. /// - /// If both `Schema` and `Query` have the same data type, the data in the `Query` is obtained. + /// If both `Schema` and `Query` have the same data type, the data in the + /// `Query` is obtained. /// /// # Errors /// @@ -41,7 +48,8 @@ pub trait DataContext<'a> { /// It will panic if the specified data type does not exist. fn data_unchecked(&self) -> &'a D; - /// Gets the global data defined in the `Context` or `Schema` or `None` if the specified type data does not exist. + /// Gets the global data defined in the `Context` or `Schema` or `None` if + /// the specified type data does not exist. fn data_opt(&self) -> Option<&'a D>; } @@ -87,8 +95,8 @@ pub type ContextDirective<'a> = ContextBase<'a, &'a Positioned>; /// A segment in the path to the current query. /// -/// This is a borrowed form of [`PathSegment`](enum.PathSegment.html) used during execution instead -/// of passed back when errors occur. +/// This is a borrowed form of [`PathSegment`](enum.PathSegment.html) used +/// during execution instead of passed back when errors occur. #[derive(Debug, Clone, Copy, Serialize)] #[serde(untagged)] pub enum QueryPathSegment<'a> { @@ -138,7 +146,8 @@ impl<'a> Display for QueryPathNode<'a> { impl<'a> QueryPathNode<'a> { /// Get the current field name. /// - /// This traverses all the parents of the node until it finds one that is a field name. + /// This traverses all the parents of the node until it finds one that is a + /// field name. pub fn field_name(&self) -> &str { std::iter::once(self) .chain(self.parents()) @@ -192,12 +201,14 @@ impl<'a> QueryPathNode<'a> { } } -/// An iterator over the parents of a [`QueryPathNode`](struct.QueryPathNode.html). +/// An iterator over the parents of a +/// [`QueryPathNode`](struct.QueryPathNode.html). #[derive(Debug, Clone)] pub struct Parents<'a>(&'a QueryPathNode<'a>); impl<'a> Parents<'a> { - /// Get the current query path node, which the next call to `next` will get the parents of. + /// Get the current query path node, which the next call to `next` will get + /// the parents of. #[must_use] pub fn current(&self) -> &'a QueryPathNode<'a> { self.0 @@ -344,14 +355,16 @@ impl<'a, T> ContextBase<'a, T> { /// Report a resolver error. /// - /// When implementing `OutputType`, if an error occurs, call this function to report this error and return `Value::Null`. + /// When implementing `OutputType`, if an error occurs, call this function + /// to report this error and return `Value::Null`. pub fn add_error(&self, error: ServerError) { self.query_env.errors.lock().unwrap().push(error); } /// Gets the global data defined in the `Context` or `Schema`. /// - /// If both `Schema` and `Query` have the same data type, the data in the `Query` is obtained. + /// If both `Schema` and `Query` have the same data type, the data in the + /// `Query` is obtained. /// /// # Errors /// @@ -375,7 +388,8 @@ impl<'a, T> ContextBase<'a, T> { .unwrap_or_else(|| panic!("Data `{}` does not exist.", std::any::type_name::())) } - /// Gets the global data defined in the `Context` or `Schema` or `None` if the specified type data does not exist. + /// Gets the global data defined in the `Context` or `Schema` or `None` if + /// the specified type data does not exist. pub fn data_opt(&self) -> Option<&'a D> { self.query_env .ctx_data @@ -391,15 +405,14 @@ impl<'a, T> ContextBase<'a, T> { /// # Examples /// /// ```no_run - /// use async_graphql::*; /// use ::http::header::ACCESS_CONTROL_ALLOW_ORIGIN; + /// use async_graphql::*; /// /// struct Query; /// /// #[Object] /// impl Query { /// async fn greet(&self, ctx: &Context<'_>) -> String { - /// /// let header_exists = ctx.http_header_contains("Access-Control-Allow-Origin"); /// assert!(!header_exists); /// @@ -422,27 +435,27 @@ impl<'a, T> ContextBase<'a, T> { /// Sets a HTTP header to response. /// - /// If the header was not currently set on the response, then `None` is returned. + /// If the header was not currently set on the response, then `None` is + /// returned. /// - /// If the response already contained this header then the new value is associated with this key - /// and __all the previous values are removed__, however only a the first previous - /// value is returned. + /// If the response already contained this header then the new value is + /// associated with this key and __all the previous values are + /// removed__, however only a the first previous value is returned. /// - /// See [`http::HeaderMap`] for more details on the underlying implementation + /// See [`http::HeaderMap`] for more details on the underlying + /// implementation /// /// # Examples /// /// ```no_run + /// use ::http::{header::ACCESS_CONTROL_ALLOW_ORIGIN, HeaderValue}; /// use async_graphql::*; - /// use ::http::header::ACCESS_CONTROL_ALLOW_ORIGIN; - /// use ::http::HeaderValue; /// /// struct Query; /// /// #[Object] /// impl Query { /// async fn greet(&self, ctx: &Context<'_>) -> String { - /// /// // Headers can be inserted using the `http` constants /// let was_in_headers = ctx.insert_http_header(ACCESS_CONTROL_ALLOW_ORIGIN, "*"); /// assert_eq!(was_in_headers, None); @@ -479,19 +492,22 @@ impl<'a, T> ContextBase<'a, T> { /// Sets a HTTP header to response. /// - /// If the header was not currently set on the response, then `false` is returned. + /// If the header was not currently set on the response, then `false` is + /// returned. /// - /// If the response did have this header then the new value is appended to the end of the - /// list of values currently associated with the key, however the key is not updated - /// _(which is important for types that can be `==` without being identical)_. + /// If the response did have this header then the new value is appended to + /// the end of the list of values currently associated with the key, + /// however the key is not updated _(which is important for types that + /// can be `==` without being identical)_. /// - /// See [`http::HeaderMap`] for more details on the underlying implementation + /// See [`http::HeaderMap`] for more details on the underlying + /// implementation /// /// # Examples /// /// ```no_run - /// use async_graphql::*; /// use ::http::header::SET_COOKIE; + /// use async_graphql::*; /// /// struct Query; /// @@ -679,7 +695,11 @@ impl<'a> ContextBase<'a, &'a Positioned> { /// #[Object] /// impl Query { /// async fn obj(&self, ctx: &Context<'_>) -> MyObj { - /// let fields = ctx.field().selection_set().map(|field| field.name()).collect::>(); + /// let fields = ctx + /// .field() + /// .selection_set() + /// .map(|field| field.name()) + /// .collect::>(); /// assert_eq!(fields, vec!["a", "b", "c"]); /// MyObj { a: 1, b: 2, c: 3 } /// } @@ -689,9 +709,11 @@ impl<'a> ContextBase<'a, &'a Positioned> { /// let schema = Schema::new(Query, EmptyMutation, EmptySubscription); /// assert!(schema.execute("{ obj { a b c }}").await.is_ok()); /// assert!(schema.execute("{ obj { a ... { b c } }}").await.is_ok()); - /// assert!(schema.execute("{ obj { a ... BC }} fragment BC on MyObj { b c }").await.is_ok()); + /// assert!(schema + /// .execute("{ obj { a ... BC }} fragment BC on MyObj { b c }") + /// .await + /// .is_ok()); /// # }); - /// /// ``` pub fn field(&self) -> SelectionField { SelectionField { diff --git a/src/custom_directive.rs b/src/custom_directive.rs index da7d9e98..f1551c17 100644 --- a/src/custom_directive.rs +++ b/src/custom_directive.rs @@ -1,7 +1,7 @@ -use crate::extensions::ResolveFut; -use crate::parser::types::Directive; -use crate::registry::Registry; -use crate::{Context, ContextDirective, ServerResult, Value}; +use crate::{ + extensions::ResolveFut, parser::types::Directive, registry::Registry, Context, + ContextDirective, ServerResult, Value, +}; #[doc(hidden)] pub trait CustomDirectiveFactory: Send + Sync + 'static { diff --git a/src/dataloader/cache.rs b/src/dataloader/cache.rs index 06b2db65..53395baf 100644 --- a/src/dataloader/cache.rs +++ b/src/dataloader/cache.rs @@ -1,8 +1,9 @@ -use std::borrow::Cow; -use std::collections::hash_map::RandomState; -use std::collections::HashMap; -use std::hash::{BuildHasher, Hash}; -use std::marker::PhantomData; +use std::{ + borrow::Cow, + collections::{hash_map::RandomState, HashMap}, + hash::{BuildHasher, Hash}, + marker::PhantomData, +}; /// Factory for creating cache storage. pub trait CacheFactory: Send + Sync + 'static { @@ -23,10 +24,12 @@ pub trait CacheStorage: Send + Sync + 'static { /// The value type of the record. type Value: Send + Sync + Clone + 'static; - /// Returns a reference to the value of the key in the cache or None if it is not present in the cache. + /// Returns a reference to the value of the key in the cache or None if it + /// is not present in the cache. fn get(&mut self, key: &Self::Key) -> Option<&Self::Value>; - /// Puts a key-value pair into the cache. If the key already exists in the cache, then it updates the key's value. + /// Puts a key-value pair into the cache. If the key already exists in the + /// cache, then it updates the key's value. fn insert(&mut self, key: Cow<'_, Self::Key>, val: Cow<'_, Self::Value>); /// Removes the value corresponding to the key from the cache. diff --git a/src/dataloader/mod.rs b/src/dataloader/mod.rs index 9d240803..f9d998c6 100644 --- a/src/dataloader/mod.rs +++ b/src/dataloader/mod.rs @@ -58,21 +58,24 @@ mod cache; -use std::any::{Any, TypeId}; -use std::borrow::Cow; -use std::collections::{HashMap, HashSet}; -use std::hash::Hash; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::{Arc, Mutex}; -use std::time::Duration; +use std::{ + any::{Any, TypeId}, + borrow::Cow, + collections::{HashMap, HashSet}, + hash::Hash, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, Mutex, + }, + time::Duration, +}; +pub use cache::{CacheFactory, CacheStorage, HashMapCache, LruCache, NoCache}; use fnv::FnvHashMap; use futures_channel::oneshot; use futures_timer::Delay; use futures_util::future::BoxFuture; -pub use cache::{CacheFactory, CacheStorage, HashMapCache, LruCache, NoCache}; - #[allow(clippy::type_complexity)] struct ResSender> { use_cache_values: HashMap, @@ -231,9 +234,11 @@ impl DataLoader { Self { delay, ..self } } - /// pub fn Specify the max batch size for loading data, the default is `1000`. + /// pub fn Specify the max batch size for loading data, the default is + /// `1000`. /// - /// If the keys waiting to be loaded reach the threshold, they are loaded immediately. + /// If the keys waiting to be loaded reach the threshold, they are loaded + /// immediately. #[must_use] pub fn max_batch_size(self, max_batch_size: usize) -> Self { Self { @@ -387,7 +392,8 @@ impl DataLoader { /// Feed some data into the cache. /// - /// **NOTE: If the cache type is [NoCache], this function will not take effect. ** + /// **NOTE: If the cache type is [NoCache], this function will not take + /// effect. ** pub async fn feed_many(&self, values: I) where K: Send + Sync + Hash + Eq + Clone + 'static, @@ -410,7 +416,8 @@ impl DataLoader { /// Feed some data into the cache. /// - /// **NOTE: If the cache type is [NoCache], this function will not take effect. ** + /// **NOTE: If the cache type is [NoCache], this function will not take + /// effect. ** pub async fn feed_one(&self, key: K, value: T::Value) where K: Send + Sync + Hash + Eq + Clone + 'static, @@ -421,7 +428,8 @@ impl DataLoader { /// Clears the cache. /// - /// **NOTE: If the cache type is [NoCache], this function will not take effect. ** + /// **NOTE: If the cache type is [NoCache], this function will not take + /// effect. ** pub fn clear(&self) where K: Send + Sync + Hash + Eq + Clone + 'static, @@ -440,10 +448,12 @@ impl DataLoader { #[cfg(test)] mod tests { - use super::*; - use fnv::FnvBuildHasher; use std::sync::Arc; + use fnv::FnvBuildHasher; + + use super::*; + struct MyLoader; #[async_trait::async_trait] diff --git a/src/error.rs b/src/error.rs index bb154319..389a82d6 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,8 +1,10 @@ -use std::any::Any; -use std::collections::BTreeMap; -use std::fmt::{self, Debug, Display, Formatter}; -use std::marker::PhantomData; -use std::sync::Arc; +use std::{ + any::Any, + collections::BTreeMap, + fmt::{self, Debug, Display, Formatter}, + marker::PhantomData, + sync::Arc, +}; use serde::{Deserialize, Serialize}; use thiserror::Error; @@ -91,22 +93,31 @@ impl ServerError { /// # Examples /// /// ```rust - /// use async_graphql::*; /// use std::io::ErrorKind; /// + /// use async_graphql::*; + /// /// struct Query; /// /// #[Object] /// impl Query { /// async fn value(&self) -> Result { - /// Err(Error::new_with_source(std::io::Error::new(ErrorKind::Other, "my error"))) + /// Err(Error::new_with_source(std::io::Error::new( + /// ErrorKind::Other, + /// "my error", + /// ))) /// } /// } /// /// let schema = Schema::new(Query, EmptyMutation, EmptySubscription); /// /// # tokio::runtime::Runtime::new().unwrap().block_on(async move { - /// let err = schema.execute("{ value }").await.into_result().unwrap_err().remove(0); + /// let err = schema + /// .execute("{ value }") + /// .await + /// .into_result() + /// .unwrap_err() + /// .remove(0); /// assert!(err.source::().is_some()); /// # }); /// ``` @@ -147,8 +158,8 @@ impl From for ServerError { /// A segment of path to a resolver. /// -/// This is like [`QueryPathSegment`](enum.QueryPathSegment.html), but owned and used as a part of -/// errors instead of during execution. +/// This is like [`QueryPathSegment`](enum.QueryPathSegment.html), but owned and +/// used as a part of errors instead of during execution. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(untagged)] pub enum PathSegment { @@ -163,7 +174,8 @@ pub type ServerResult = std::result::Result; /// An error parsing an input value. /// -/// This type is generic over T as it uses T's type name when converting to a regular error. +/// This type is generic over T as it uses T's type name when converting to a +/// regular error. #[derive(Debug)] pub struct InputValueError { message: String, @@ -190,8 +202,8 @@ impl InputValueError { /// A custom error message. /// - /// Any type that implements `Display` is automatically converted to this if you use the `?` - /// operator. + /// Any type that implements `Display` is automatically converted to this if + /// you use the `?` operator. #[must_use] pub fn custom(msg: impl Display) -> Self { Self::new(format!(r#"Failed to parse "{}": {}"#, T::type_name(), msg)) @@ -263,8 +275,8 @@ impl Error { } } - /// Create an error with a type that implements `Display`, and it will also set the - /// `source` of the error to this value. + /// Create an error with a type that implements `Display`, and it will also + /// set the `source` of the error to this value. pub fn new_with_source(source: impl Display + Send + Sync + 'static) -> Self { Self { message: source.to_string(), @@ -339,7 +351,8 @@ pub enum ParseRequestError { #[error("Payload too large")] PayloadTooLarge, - /// The request is a batch request, but the server does not support batch requests. + /// The request is a batch request, but the server does not support batch + /// requests. #[error("Batch requests are not supported")] UnsupportedBatch, } @@ -397,8 +410,8 @@ impl ErrorExtensions for Error { } } -// implementing for &E instead of E gives the user the possibility to implement for E which does -// not conflict with this implementation acting as a fallback. +// implementing for &E instead of E gives the user the possibility to implement +// for E which does not conflict with this implementation acting as a fallback. impl ErrorExtensions for &E { fn extend(&self) -> Error { Error { @@ -409,7 +422,8 @@ impl ErrorExtensions for &E { } } -/// Extend a `Result`'s error value with [`ErrorExtensions`](trait.ErrorExtensions.html). +/// Extend a `Result`'s error value with +/// [`ErrorExtensions`](trait.ErrorExtensions.html). pub trait ResultExt: Sized { /// Extend the error value of the result with the callback. fn extend_err(self, cb: C) -> Result @@ -420,8 +434,8 @@ pub trait ResultExt: Sized { fn extend(self) -> Result; } -// This is implemented on E and not &E which means it cannot be used on foreign types. -// (see example). +// This is implemented on E and not &E which means it cannot be used on foreign +// types. (see example). impl ResultExt for std::result::Result where E: ErrorExtensions + Send + Sync + 'static, diff --git a/src/extensions/analyzer.rs b/src/extensions/analyzer.rs index dc05e458..6165e9c6 100644 --- a/src/extensions/analyzer.rs +++ b/src/extensions/analyzer.rs @@ -2,14 +2,15 @@ use std::sync::Arc; use futures_util::lock::Mutex; -use crate::extensions::{ - Extension, ExtensionContext, ExtensionFactory, NextRequest, NextValidation, +use crate::{ + extensions::{Extension, ExtensionContext, ExtensionFactory, NextRequest, NextValidation}, + value, Response, ServerError, ValidationResult, }; -use crate::{value, Response, ServerError, ValidationResult}; /// Analyzer extension /// -/// This extension will output the `analyzer` field containing `complexity` and `depth` in the response extension of each query. +/// This extension will output the `analyzer` field containing `complexity` and +/// `depth` in the response extension of each query. pub struct Analyzer; impl ExtensionFactory for Analyzer { diff --git a/src/extensions/apollo_persisted_queries.rs b/src/extensions/apollo_persisted_queries.rs index 9946c827..e6248f11 100644 --- a/src/extensions/apollo_persisted_queries.rs +++ b/src/extensions/apollo_persisted_queries.rs @@ -6,8 +6,10 @@ use futures_util::lock::Mutex; use serde::Deserialize; use sha2::{Digest, Sha256}; -use crate::extensions::{Extension, ExtensionContext, ExtensionFactory, NextPrepareRequest}; -use crate::{from_value, Request, ServerError, ServerResult}; +use crate::{ + extensions::{Extension, ExtensionContext, ExtensionFactory, NextPrepareRequest}, + from_value, Request, ServerError, ServerResult, +}; #[derive(Deserialize)] struct PersistedQuery { diff --git a/src/extensions/apollo_tracing.rs b/src/extensions/apollo_tracing.rs index e620154c..8288c479 100644 --- a/src/extensions/apollo_tracing.rs +++ b/src/extensions/apollo_tracing.rs @@ -2,13 +2,14 @@ use std::sync::Arc; use chrono::{DateTime, Utc}; use futures_util::lock::Mutex; -use serde::ser::SerializeMap; -use serde::{Serialize, Serializer}; +use serde::{ser::SerializeMap, Serialize, Serializer}; -use crate::extensions::{ - Extension, ExtensionContext, ExtensionFactory, NextExecute, NextResolve, ResolveInfo, +use crate::{ + extensions::{ + Extension, ExtensionContext, ExtensionFactory, NextExecute, NextResolve, ResolveInfo, + }, + value, Response, ServerResult, Value, }; -use crate::{value, Response, ServerResult, Value}; struct ResolveState { path: Vec, @@ -38,10 +39,11 @@ impl Serialize for ResolveState { /// Apollo tracing extension for performance tracing /// -/// Apollo Tracing works by including data in the extensions field of the GraphQL response, which is -/// reserved by the GraphQL spec for extra information that a server wants to return. That way, you -/// have access to performance traces alongside the data returned by your query. -/// It's already supported by `Apollo Engine`, and we're excited to see what other kinds of +/// Apollo Tracing works by including data in the extensions field of the +/// GraphQL response, which is reserved by the GraphQL spec for extra +/// information that a server wants to return. That way, you have access to +/// performance traces alongside the data returned by your query. It's already +/// supported by `Apollo Engine`, and we're excited to see what other kinds of /// integrations people can build on top of this format. #[cfg_attr(docsrs, doc(cfg(feature = "apollo_tracing")))] pub struct ApolloTracing; diff --git a/src/extensions/logger.rs b/src/extensions/logger.rs index de5d8115..c375b462 100644 --- a/src/extensions/logger.rs +++ b/src/extensions/logger.rs @@ -1,11 +1,10 @@ -use std::fmt::Write; -use std::sync::Arc; +use std::{fmt::Write, sync::Arc}; -use crate::extensions::{ - Extension, ExtensionContext, ExtensionFactory, NextExecute, NextParseQuery, +use crate::{ + extensions::{Extension, ExtensionContext, ExtensionFactory, NextExecute, NextParseQuery}, + parser::types::{ExecutableDocument, OperationType, Selection}, + PathSegment, Response, ServerResult, Variables, }; -use crate::parser::types::{ExecutableDocument, OperationType, Selection}; -use crate::{PathSegment, Response, ServerResult, Variables}; /// Logger extension #[cfg_attr(docsrs, doc(cfg(feature = "log")))] diff --git a/src/extensions/mod.rs b/src/extensions/mod.rs index 52a2a311..d9b40b01 100644 --- a/src/extensions/mod.rs +++ b/src/extensions/mod.rs @@ -12,6 +12,14 @@ mod opentelemetry; #[cfg(feature = "tracing")] mod tracing; +use std::{ + any::{Any, TypeId}, + future::Future, + sync::Arc, +}; + +use futures_util::stream::BoxStream; + pub use self::analyzer::Analyzer; #[cfg(feature = "apollo_tracing")] pub use self::apollo_tracing::ApolloTracing; @@ -21,17 +29,9 @@ pub use self::logger::Logger; pub use self::opentelemetry::OpenTelemetry; #[cfg(feature = "tracing")] pub use self::tracing::Tracing; - -use std::any::{Any, TypeId}; -use std::future::Future; -use std::sync::Arc; - -use futures_util::stream::BoxStream; - -use crate::parser::types::ExecutableDocument; use crate::{ - Data, DataContext, Error, QueryPathNode, Request, Response, Result, SchemaEnv, ServerError, - ServerResult, ValidationResult, Value, Variables, + parser::types::ExecutableDocument, Data, DataContext, Error, QueryPathNode, Request, Response, + Result, SchemaEnv, ServerError, ServerResult, ValidationResult, Value, Variables, }; /// Context for extension @@ -73,7 +73,8 @@ impl<'a> ExtensionContext<'a> { /// Gets the global data defined in the `Context` or `Schema`. /// - /// If both `Schema` and `Query` have the same data type, the data in the `Query` is obtained. + /// If both `Schema` and `Query` have the same data type, the data in the + /// `Query` is obtained. /// /// # Errors /// @@ -97,7 +98,8 @@ impl<'a> ExtensionContext<'a> { .unwrap_or_else(|| panic!("Data `{}` does not exist.", std::any::type_name::())) } - /// Gets the global data defined in the `Context` or `Schema` or `None` if the specified type data does not exist. + /// Gets the global data defined in the `Context` or `Schema` or `None` if + /// the specified type data does not exist. pub fn data_opt(&self) -> Option<&'a D> { self.query_data .and_then(|query_data| query_data.get(&TypeId::of::())) diff --git a/src/extensions/opentelemetry.rs b/src/extensions/opentelemetry.rs index 3ae9e7a9..f0f5aa67 100644 --- a/src/extensions/opentelemetry.rs +++ b/src/extensions/opentelemetry.rs @@ -2,16 +2,19 @@ use std::sync::Arc; use async_graphql_parser::types::ExecutableDocument; use async_graphql_value::Variables; -use futures_util::stream::BoxStream; -use futures_util::TryFutureExt; -use opentelemetry::trace::{FutureExt, SpanKind, TraceContextExt, Tracer}; -use opentelemetry::{Context as OpenTelemetryContext, Key}; - -use crate::extensions::{ - Extension, ExtensionContext, ExtensionFactory, NextExecute, NextParseQuery, NextRequest, - NextResolve, NextSubscribe, NextValidation, ResolveInfo, +use futures_util::{stream::BoxStream, TryFutureExt}; +use opentelemetry::{ + trace::{FutureExt, SpanKind, TraceContextExt, Tracer}, + Context as OpenTelemetryContext, Key, +}; + +use crate::{ + extensions::{ + Extension, ExtensionContext, ExtensionFactory, NextExecute, NextParseQuery, NextRequest, + NextResolve, NextSubscribe, NextValidation, ResolveInfo, + }, + Response, ServerError, ServerResult, ValidationResult, Value, }; -use crate::{Response, ServerError, ServerResult, ValidationResult, Value}; const KEY_SOURCE: Key = Key::from_static_str("graphql.source"); const KEY_VARIABLES: Key = Key::from_static_str("graphql.variables"); diff --git a/src/extensions/tracing.rs b/src/extensions/tracing.rs index 97f257ed..2e4adc8e 100644 --- a/src/extensions/tracing.rs +++ b/src/extensions/tracing.rs @@ -1,16 +1,17 @@ use std::sync::Arc; -use futures_util::stream::BoxStream; -use futures_util::TryFutureExt; +use futures_util::{stream::BoxStream, TryFutureExt}; use tracing_futures::Instrument; use tracinglib::{span, Level}; -use crate::extensions::{ - Extension, ExtensionContext, ExtensionFactory, NextExecute, NextParseQuery, NextRequest, - NextResolve, NextSubscribe, NextValidation, ResolveInfo, +use crate::{ + extensions::{ + Extension, ExtensionContext, ExtensionFactory, NextExecute, NextParseQuery, NextRequest, + NextResolve, NextSubscribe, NextValidation, ResolveInfo, + }, + parser::types::ExecutableDocument, + Response, ServerError, ServerResult, ValidationResult, Value, Variables, }; -use crate::parser::types::ExecutableDocument; -use crate::{Response, ServerError, ServerResult, ValidationResult, Value, Variables}; /// Tracing extension /// @@ -21,8 +22,7 @@ use crate::{Response, ServerError, ServerResult, ValidationResult, Value, Variab /// # Examples /// /// ```no_run -/// use async_graphql::*; -/// use async_graphql::extensions::Tracing; +/// use async_graphql::{extensions::Tracing, *}; /// /// #[derive(SimpleObject)] /// struct Query { diff --git a/src/guard.rs b/src/guard.rs index 23d26b45..8285e4ed 100644 --- a/src/guard.rs +++ b/src/guard.rs @@ -4,7 +4,8 @@ use crate::{Context, Result}; /// Field guard /// -/// Guard is a pre-condition for a field that is resolved if `Ok(())` is returned, otherwise an error is returned. +/// Guard is a pre-condition for a field that is resolved if `Ok(())` is +/// returned, otherwise an error is returned. #[async_trait::async_trait] pub trait Guard { /// Check whether the guard will allow access to the field. diff --git a/src/http/mod.rs b/src/http/mod.rs index 8adf081e..9d0cb552 100644 --- a/src/http/mod.rs +++ b/src/http/mod.rs @@ -5,16 +5,15 @@ mod multipart; mod playground_source; mod websocket; +use futures_util::io::{AsyncRead, AsyncReadExt}; pub use graphiql_source::graphiql_source; +use mime; pub use multipart::MultipartOptions; pub use playground_source::{playground_source, GraphQLPlaygroundConfig}; pub use websocket::{ ClientMessage, Protocols as WebSocketProtocols, WebSocket, WsMessage, ALL_WEBSOCKET_PROTOCOLS, }; -use futures_util::io::{AsyncRead, AsyncReadExt}; -use mime; - use crate::{BatchRequest, ParseRequestError, Request}; /// Receive a GraphQL request from a content type and body. @@ -62,7 +61,8 @@ pub async fn receive_batch_body( } /// Recieves a GraphQL query which is either cbor or json but NOT multipart -/// This method is only to avoid recursive calls with [``receive_batch_body``] and [``multipart::receive_batch_multipart``] +/// This method is only to avoid recursive calls with [``receive_batch_body``] +/// and [``multipart::receive_batch_multipart``] pub(super) async fn receive_batch_body_no_multipart( content_type: &mime::Mime, body: impl AsyncRead + Send, diff --git a/src/http/multipart.rs b/src/http/multipart.rs index 0ca35d53..3b9bab41 100644 --- a/src/http/multipart.rs +++ b/src/http/multipart.rs @@ -1,10 +1,11 @@ -use std::collections::HashMap; -use std::io::{self, Seek, SeekFrom, Write}; -use std::pin::Pin; -use std::task::{Context, Poll}; +use std::{ + collections::HashMap, + io::{self, Seek, SeekFrom, Write}, + pin::Pin, + task::{Context, Poll}, +}; -use futures_util::io::AsyncRead; -use futures_util::stream::Stream; +use futures_util::{io::AsyncRead, stream::Stream}; use multer::{Constraints, Multipart, SizeLimit}; use pin_project_lite::pin_project; @@ -90,8 +91,9 @@ pub(super) async fn receive_batch_multipart( // Note: we actually differ here from the inoffical spec for this: // (https://github.com/jaydenseric/graphql-multipart-request-spec#multipart-form-field-structure) // It says: "map: A JSON encoded map of where files occurred in the operations. - // For each file, the key is the file multipart form field name and the value is an array of operations paths." - // However, I think, that since we accept CBOR as operation, which is valid, we should also accept it + // For each file, the key is the file multipart form field name and the value is + // an array of operations paths." However, I think, that + // since we accept CBOR as operation, which is valid, we should also accept it // as the mapping for the files. #[cfg(feature = "cbor")] (mime::OCTET_STREAM, _) | (mime::APPLICATION, mime::OCTET_STREAM) => { diff --git a/src/http/playground_source.rs b/src/http/playground_source.rs index 0a1acb45..59aa2b31 100644 --- a/src/http/playground_source.rs +++ b/src/http/playground_source.rs @@ -626,9 +626,10 @@ impl<'a> GraphQLPlaygroundConfig<'a> { #[cfg(test)] mod tests { - use super::*; use indexmap::IndexMap; + use super::*; + #[test] fn test_with_setting_can_use_any_json_value() { let settings = GraphQLPlaygroundConfig::new("") diff --git a/src/http/websocket.rs b/src/http/websocket.rs index 1448a96a..e3060631 100644 --- a/src/http/websocket.rs +++ b/src/http/websocket.rs @@ -1,15 +1,18 @@ //! WebSocket transport for subscription -use std::collections::HashMap; -use std::future::Future; -use std::pin::Pin; -use std::sync::Arc; -use std::task::{Context, Poll}; +use std::{ + collections::HashMap, + future::Future, + pin::Pin, + sync::Arc, + task::{Context, Poll}, +}; -use futures_util::future::Ready; -use futures_util::stream::Stream; -use futures_util::FutureExt; -use futures_util::{future::BoxFuture, StreamExt}; +use futures_util::{ + future::{BoxFuture, Ready}, + stream::Stream, + FutureExt, StreamExt, +}; use pin_project_lite::pin_project; use serde::{Deserialize, Serialize}; @@ -29,7 +32,8 @@ pub enum WsMessage { } impl WsMessage { - /// Returns the contained [WsMessage::Text] value, consuming the `self` value. + /// Returns the contained [WsMessage::Text] value, consuming the `self` + /// value. /// /// Because this function may panic, its use is generally discouraged. /// @@ -43,7 +47,8 @@ impl WsMessage { } } - /// Returns the contained [WsMessage::Close] value, consuming the `self` value. + /// Returns the contained [WsMessage::Close] value, consuming the `self` + /// value. /// /// Because this function may panic, its use is generally discouraged. /// @@ -136,8 +141,9 @@ where /// Specify a connection data. /// /// This data usually comes from HTTP requests. - /// When the `GQL_CONNECTION_INIT` message is received, this data will be merged with the data - /// returned by the closure specified by `with_initializer` into the final subscription context data. + /// When the `GQL_CONNECTION_INIT` message is received, this data will be + /// merged with the data returned by the closure specified by + /// `with_initializer` into the final subscription context data. #[must_use] pub fn connection_data(mut self, data: Data) -> Self { self.connection_data = Some(data); @@ -146,8 +152,8 @@ where /// Specify a connection initialize callback function. /// - /// This function if present, will be called with the data sent by the client in the - /// [`GQL_CONNECTION_INIT` message](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_connection_init). + /// This function if present, will be called with the data sent by the + /// client in the [`GQL_CONNECTION_INIT` message](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_connection_init). /// From that point on the returned data will be accessible to all requests. #[must_use] pub fn on_connection_init( @@ -365,7 +371,7 @@ impl std::str::FromStr for Protocols { /// A websocket message received from the client #[derive(Deserialize)] #[serde(tag = "type", rename_all = "snake_case")] -#[allow(clippy::large_enum_variant)] //Request is at fault +#[allow(clippy::large_enum_variant)] // Request is at fault pub enum ClientMessage { /// A new connection ConnectionInit { @@ -377,8 +383,8 @@ pub enum ClientMessage { Start { /// Message ID id: String, - /// The GraphQL Request - this can be modified by protocol implementors to add files - /// uploads. + /// The GraphQL Request - this can be modified by protocol implementors + /// to add files uploads. payload: Request, }, /// The end of a Websocket subscription @@ -389,7 +395,8 @@ pub enum ClientMessage { }, /// Connection terminated by the client ConnectionTerminate, - /// Useful for detecting failed connections, displaying latency metrics or other types of network probing. + /// Useful for detecting failed connections, displaying latency metrics or + /// other types of network probing. /// /// https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md#ping Ping { diff --git a/src/lib.rs b/src/lib.rs index df612cc0..13d29436 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,7 +43,8 @@ //! * Rustfmt friendly (Procedural Macro) //! * Custom scalars //! * Minimal overhead -//! * Easy integration ([poem](https://crates.io/crates/poem), actix_web, tide, warp, rocket ...) +//! * Easy integration ([poem](https://crates.io/crates/poem), actix_web, tide, +//! warp, rocket ...) //! * File upload (Multipart request) //! * Subscriptions (WebSocket transport) //! * Custom extensions @@ -56,20 +57,27 @@ //! //! ## Crate features //! -//! This crate offers the following features, all of which are not activated by default: +//! This crate offers the following features, all of which are not activated by +//! default: //! -//! - `apollo_tracing`: Enable the [Apollo tracing extension](extensions/struct.ApolloTracing.html). -//! - `apollo_persisted_queries`: Enable the [Apollo persisted queries extension](extensions/apollo_persisted_queries/struct.ApolloPersistedQueries.html). +//! - `apollo_tracing`: Enable the [Apollo tracing +//! extension](extensions/struct.ApolloTracing.html). +//! - `apollo_persisted_queries`: Enable the [Apollo persisted queries +//! extension](extensions/apollo_persisted_queries/struct. +//! ApolloPersistedQueries.html). //! - `log`: Enable the [logger extension](extensions/struct.Logger.html). //! - `tracing`: Enable the [tracing extension](extensions/struct.Tracing.html). -//! - `opentelemetry`: Enable the [OpenTelemetry extension](extensions/struct.OpenTelemetry.html). -//! - `unblock`: Support [asynchronous reader for Upload](types/struct.Upload.html) +//! - `opentelemetry`: Enable the [OpenTelemetry +//! extension](extensions/struct.OpenTelemetry.html). +//! - `unblock`: Support [asynchronous reader for +//! Upload](types/struct.Upload.html) //! - `bson`: Integrate with the [`bson` crate](https://crates.io/crates/bson). //! - `chrono`: Integrate with the [`chrono` crate](https://crates.io/crates/chrono). //! - `chrono-tz`: Integrate with the [`chrono-tz` crate](https://crates.io/crates/chrono-tz). //! - `url`: Integrate with the [`url` crate](https://crates.io/crates/url). //! - `uuid`: Integrate with the [`uuid` crate](https://crates.io/crates/uuid). -//! - `string_number`: Enable the [StringNumber](types/struct.StringNumber.html). +//! - `string_number`: Enable the +//! [StringNumber](types/struct.StringNumber.html). //! - `dataloader`: Support [DataLoader](dataloader/struct.DataLoader.html). //! - `decimal`: Integrate with the [`rust_decimal` crate](https://crates.io/crates/rust_decimal). //! - `cbor`: Support for [serde_cbor](https://crates.io/crates/serde_cbor). @@ -125,7 +133,6 @@ //! ``` //! //! Now a HTML report is available at `benchmark/target/criterion/report`. -//! #![deny(clippy::all)] // #![deny(clippy::pedantic)] @@ -192,58 +199,56 @@ pub mod validators; #[doc(hidden)] pub mod registry; -#[doc(hidden)] -pub use async_stream; -#[doc(hidden)] -pub use async_trait; -#[doc(hidden)] -pub use context::ContextSelectionSet; -#[doc(hidden)] -pub use futures_util; -#[doc(hidden)] -pub use indexmap; -#[doc(hidden)] -pub use static_assertions; -#[doc(hidden)] -pub use subscription::SubscriptionType; - pub use async_graphql_parser as parser; pub use async_graphql_value::{ from_value, to_value, value, ConstValue as Value, DeserializerError, Name, Number, SerializerError, Variables, }; +#[doc(hidden)] +pub use async_stream; +#[doc(hidden)] +pub use async_trait; pub use base::{ ComplexObject, Description, InputObjectType, InputType, InterfaceType, ObjectType, - OneofObjectType, OutputType, UnionType, + OneofObjectType, OutputType, TypeName, UnionType, }; +#[doc(hidden)] +pub use context::ContextSelectionSet; +pub use context::*; pub use custom_directive::{CustomDirective, CustomDirectiveFactory}; pub use error::{ Error, ErrorExtensionValues, ErrorExtensions, InputValueError, InputValueResult, ParseRequestError, PathSegment, Result, ResultExt, ServerError, ServerResult, }; pub use extensions::ResolveFut; +#[doc(hidden)] +pub use futures_util; pub use guard::{Guard, GuardExt}; +#[doc(hidden)] +pub use indexmap; pub use look_ahead::Lookahead; +#[doc(no_inline)] +pub use parser::{Pos, Positioned}; pub use registry::CacheControl; pub use request::{BatchRequest, Request}; #[doc(no_inline)] pub use resolver_utils::{ContainerType, EnumType, ScalarType}; pub use response::{BatchResponse, Response}; pub use schema::{Schema, SchemaBuilder, SchemaEnv}; +#[doc(hidden)] +pub use static_assertions; +#[doc(hidden)] +pub use subscription::SubscriptionType; +pub use types::*; pub use validation::{ValidationMode, ValidationResult, VisitorContext}; pub use validators::CustomValidator; -pub use context::*; -#[doc(no_inline)] -pub use parser::{Pos, Positioned}; -pub use types::*; - -/// An alias of [async_graphql::Error](struct.Error.html). Present for backward compatibility -/// reasons. +/// An alias of [async_graphql::Error](struct.Error.html). Present for backward +/// compatibility reasons. pub type FieldError = Error; -/// An alias of [async_graphql::Result](type.Result.html). Present for backward compatibility -/// reasons. +/// An alias of [async_graphql::Result](type.Result.html). Present for backward +/// compatibility reasons. pub type FieldResult = Result; #[doc = include_str!("docs/complex_object.md")] diff --git a/src/look_ahead.rs b/src/look_ahead.rs index e706e09d..2486b4c5 100644 --- a/src/look_ahead.rs +++ b/src/look_ahead.rs @@ -1,8 +1,9 @@ use std::collections::HashMap; -use crate::parser::types::{Field, FragmentDefinition, Selection, SelectionSet}; -use crate::Context; -use crate::{Name, Positioned, SelectionField}; +use crate::{ + parser::types::{Field, FragmentDefinition, Selection, SelectionSet}, + Context, Name, Positioned, SelectionField, +}; /// A selection performed by a query. pub struct Lookahead<'a> { @@ -24,11 +25,11 @@ impl<'a> Lookahead<'a> { } } - /// Get the field of the selection set with the specified name. This will ignore - /// aliases. + /// Get the field of the selection set with the specified name. This will + /// ignore aliases. /// - /// For example, calling `.field("a")` on `{ a { b } }` will return a lookahead that - /// represents `{ b }`. + /// For example, calling `.field("a")` on `{ a { b } }` will return a + /// lookahead that represents `{ b }`. #[must_use] pub fn field(&self, name: &str) -> Self { let mut fields = Vec::new(); @@ -49,9 +50,11 @@ impl<'a> Lookahead<'a> { !self.fields.is_empty() } - /// Get the `SelectionField`s for each of the fields covered by this `Lookahead`. + /// Get the `SelectionField`s for each of the fields covered by this + /// `Lookahead`. /// - /// There will be multiple fields in situations where the same field is queried twice. + /// There will be multiple fields in situations where the same field is + /// queried twice. pub fn selection_fields(&self) -> Vec> { self.fields .iter() @@ -75,7 +78,8 @@ impl<'a> From> for Lookahead<'a> { } /// Convert a slice of `SelectionField`s to a `Lookahead`. -/// Assumes all `SelectionField`s are from the same query and thus have the same fragments. +/// Assumes all `SelectionField`s are from the same query and thus have the same +/// fragments. /// /// Fails if either no `SelectionField`s were provided. impl<'a> TryFrom<&[SelectionField<'a>]> for Lookahead<'a> { diff --git a/src/model/directive.rs b/src/model/directive.rs index db032ac8..ddf0ef49 100644 --- a/src/model/directive.rs +++ b/src/model/directive.rs @@ -1,9 +1,9 @@ use std::collections::HashSet; -use crate::model::__InputValue; -use crate::{registry, Enum, Object}; +use crate::{model::__InputValue, registry, Enum, Object}; -/// A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies. +/// A Directive can be adjacent to many parts of the GraphQL language, a +/// __DirectiveLocation describes one such possible adjacencies. #[derive(Debug, Enum, Copy, Clone, Eq, PartialEq)] #[graphql(internal, name = "__DirectiveLocation")] #[allow(non_camel_case_types)] @@ -72,9 +72,13 @@ pub struct __Directive<'a> { pub directive: &'a registry::MetaDirective, } -/// A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document. +/// A Directive provides a way to describe alternate runtime execution and type +/// validation behavior in a GraphQL document. /// -/// In some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor. +/// In some cases, you need to provide options to alter GraphQL's execution +/// behavior in ways field arguments will not suffice, such as conditionally +/// including or skipping a field. Directives provide this by describing +/// additional information to the executor. #[Object(internal, name = "__Directive")] impl<'a> __Directive<'a> { #[inline] diff --git a/src/model/enum_value.rs b/src/model/enum_value.rs index 78a059dc..6598da1d 100644 --- a/src/model/enum_value.rs +++ b/src/model/enum_value.rs @@ -5,7 +5,9 @@ pub struct __EnumValue<'a> { pub value: &'a registry::MetaEnumValue, } -/// One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string. +/// One possible value for a given Enum. Enum values are unique values, not a +/// placeholder for a string or numeric value. However an Enum value is returned +/// in a JSON response as a string. #[Object(internal, name = "__EnumValue")] impl<'a> __EnumValue<'a> { #[inline] diff --git a/src/model/field.rs b/src/model/field.rs index e5b4ec17..c8979975 100644 --- a/src/model/field.rs +++ b/src/model/field.rs @@ -1,8 +1,11 @@ use std::collections::HashSet; -use crate::model::{__InputValue, __Type}; -use crate::registry::is_visible; -use crate::{registry, Context, Object}; +use crate::{ + model::{__InputValue, __Type}, + registry, + registry::is_visible, + Context, Object, +}; pub struct __Field<'a> { pub registry: &'a registry::Registry, @@ -10,7 +13,8 @@ pub struct __Field<'a> { pub field: &'a registry::MetaField, } -/// Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type. +/// Object and Interface types are described by a list of Fields, each of which +/// has a name, potentially a list of arguments, and a return type. #[Object(internal, name = "__Field")] impl<'a> __Field<'a> { #[inline] diff --git a/src/model/input_value.rs b/src/model/input_value.rs index a7a84628..78953922 100644 --- a/src/model/input_value.rs +++ b/src/model/input_value.rs @@ -1,7 +1,6 @@ use std::collections::HashSet; -use crate::model::__Type; -use crate::{registry, Object}; +use crate::{model::__Type, registry, Object}; pub struct __InputValue<'a> { pub registry: &'a registry::Registry, @@ -9,7 +8,9 @@ pub struct __InputValue<'a> { pub input_value: &'a registry::MetaInputValue, } -/// Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value. +/// Arguments provided to Fields or Directives and the input fields of an +/// InputObject are represented as Input Values which describe their type and +/// optionally a default value. #[Object(internal, name = "__InputValue")] impl<'a> __InputValue<'a> { #[inline] diff --git a/src/model/kind.rs b/src/model/kind.rs index 9400af3f..e3cc3a12 100644 --- a/src/model/kind.rs +++ b/src/model/kind.rs @@ -7,10 +7,12 @@ pub enum __TypeKind { /// Indicates this type is a scalar. Scalar, - /// Indicates this type is an object. `fields` and `interfaces` are valid fields. + /// Indicates this type is an object. `fields` and `interfaces` are valid + /// fields. Object, - /// Indicates this type is an interface. `fields` and `possibleTypes` are valid fields. + /// Indicates this type is an interface. `fields` and `possibleTypes` are + /// valid fields. Interface, /// Indicates this type is a union. `possibleTypes` is a valid field. diff --git a/src/model/schema.rs b/src/model/schema.rs index 2cfc2504..2449990b 100644 --- a/src/model/schema.rs +++ b/src/model/schema.rs @@ -1,7 +1,9 @@ use std::collections::HashSet; -use crate::model::{__Directive, __Type}; -use crate::{registry, Object}; +use crate::{ + model::{__Directive, __Type}, + registry, Object, +}; pub struct __Schema<'a> { registry: &'a registry::Registry, @@ -17,7 +19,9 @@ impl<'a> __Schema<'a> { } } -/// A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations. +/// A GraphQL Schema defines the capabilities of a GraphQL server. It exposes +/// all available types and directives on the server, as well as the entry +/// points for query, mutation, and subscription operations. #[Object(internal, name = "__Schema")] impl<'a> __Schema<'a> { /// A list of all types supported by this server. @@ -51,7 +55,8 @@ impl<'a> __Schema<'a> { ) } - /// If this server supports mutation, the type that mutation operations will be rooted at. + /// If this server supports mutation, the type that mutation operations will + /// be rooted at. #[inline] async fn mutation_type(&self) -> Option<__Type<'a>> { self.registry.mutation_type.as_ref().and_then(|ty| { @@ -67,7 +72,8 @@ impl<'a> __Schema<'a> { }) } - /// If this server support subscription, the type that subscription operations will be rooted at. + /// If this server support subscription, the type that subscription + /// operations will be rooted at. #[inline] async fn subscription_type(&self) -> Option<__Type<'a>> { self.registry.subscription_type.as_ref().and_then(|ty| { diff --git a/src/model/type.rs b/src/model/type.rs index 160a3aa2..60ec3411 100644 --- a/src/model/type.rs +++ b/src/model/type.rs @@ -1,8 +1,11 @@ use std::collections::HashSet; -use crate::model::{__EnumValue, __Field, __InputValue, __TypeKind}; -use crate::registry::is_visible; -use crate::{registry, Context, Object}; +use crate::{ + model::{__EnumValue, __Field, __InputValue, __TypeKind}, + registry, + registry::is_visible, + Context, Object, +}; enum TypeDetail<'a> { Named(&'a registry::MetaType), @@ -59,9 +62,15 @@ impl<'a> __Type<'a> { } } -/// The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum. +/// The fundamental unit of any GraphQL Schema is the type. There are many kinds +/// of types in GraphQL as represented by the `__TypeKind` enum. /// -/// Depending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name and description, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types. +/// Depending on the kind of a type, certain fields describe information about +/// that type. Scalar types provide no information beyond a name and +/// description, while Enum types provide their values. Object and Interface +/// types provide the fields they describe. Abstract types, Union and Interface, +/// provide the Object types possible at runtime. List and NonNull types compose +/// other types. #[Object(internal, name = "__Type")] impl<'a> __Type<'a> { #[inline] diff --git a/src/registry/cache_control.rs b/src/registry/cache_control.rs index 10a370a2..1cbb1112 100644 --- a/src/registry/cache_control.rs +++ b/src/registry/cache_control.rs @@ -22,9 +22,42 @@ /// /// # tokio::runtime::Runtime::new().unwrap().block_on(async { /// let schema = Schema::new(Query, EmptyMutation, EmptySubscription); -/// assert_eq!(schema.execute("{ value1 }").await.into_result().unwrap().cache_control, CacheControl { public: true, max_age: 30 }); -/// assert_eq!(schema.execute("{ value2 }").await.into_result().unwrap().cache_control, CacheControl { public: false, max_age: 60 }); -/// assert_eq!(schema.execute("{ value1 value2 }").await.into_result().unwrap().cache_control, CacheControl { public: false, max_age: 30 }); +/// assert_eq!( +/// schema +/// .execute("{ value1 }") +/// .await +/// .into_result() +/// .unwrap() +/// .cache_control, +/// CacheControl { +/// public: true, +/// max_age: 30 +/// } +/// ); +/// assert_eq!( +/// schema +/// .execute("{ value2 }") +/// .await +/// .into_result() +/// .unwrap() +/// .cache_control, +/// CacheControl { +/// public: false, +/// max_age: 60 +/// } +/// ); +/// assert_eq!( +/// schema +/// .execute("{ value1 value2 }") +/// .await +/// .into_result() +/// .unwrap() +/// .cache_control, +/// CacheControl { +/// public: false, +/// max_age: 30 +/// } +/// ); /// # }); /// ``` #[derive(Clone, Copy, PartialEq, Eq, Debug)] diff --git a/src/registry/mod.rs b/src/registry/mod.rs index c65d7183..22bffc12 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -2,23 +2,22 @@ mod cache_control; mod export_sdl; mod stringify_exec_doc; -use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; -use std::fmt::{self, Display, Formatter}; - -use indexmap::map::IndexMap; -use indexmap::set::IndexSet; - -pub use crate::model::__DirectiveLocation; -use crate::{ - model, Any, Context, InputType, OutputType, Positioned, ServerResult, SubscriptionType, Value, - VisitorContext, -}; -use crate::{ - parser::types::{BaseType as ParsedBaseType, Field, Type as ParsedType, VariableDefinition}, - schema::IntrospectionMode, +use std::{ + collections::{BTreeMap, BTreeSet, HashMap, HashSet}, + fmt::{self, Display, Formatter}, }; pub use cache_control::CacheControl; +use indexmap::{map::IndexMap, set::IndexSet}; + +pub use crate::model::__DirectiveLocation; +use crate::{ + model, + parser::types::{BaseType as ParsedBaseType, Field, Type as ParsedType, VariableDefinition}, + schema::IntrospectionMode, + Any, Context, InputType, OutputType, Positioned, ServerResult, SubscriptionType, Value, + VisitorContext, +}; fn strip_brackets(type_name: &str) -> Option<&str> { type_name @@ -482,7 +481,8 @@ impl Registry { } } None => { - // Inserting a fake type before calling the function allows recursive types to exist. + // Inserting a fake type before calling the function allows recursive types to + // exist. self.types.insert( name.to_string(), MetaType::Object { diff --git a/src/registry/stringify_exec_doc.rs b/src/registry/stringify_exec_doc.rs index b926156e..1fe2ca19 100644 --- a/src/registry/stringify_exec_doc.rs +++ b/src/registry/stringify_exec_doc.rs @@ -2,11 +2,13 @@ use std::fmt::{Error, Result as FmtResult, Write}; use async_graphql_value::ConstValue; -use crate::parser::types::{ - ExecutableDocument, FragmentDefinition, OperationType, Selection, SelectionSet, +use crate::{ + parser::types::{ + ExecutableDocument, FragmentDefinition, OperationType, Selection, SelectionSet, + }, + registry::{MetaInputValue, MetaType, MetaTypeName, Registry}, + Variables, }; -use crate::registry::{MetaInputValue, MetaType, MetaTypeName, Registry}; -use crate::Variables; impl Registry { pub(crate) fn stringify_exec_doc( @@ -219,8 +221,7 @@ impl Registry { #[cfg(test)] mod tests { use super::*; - use crate::parser::parse_query; - use crate::*; + use crate::{parser::parse_query, *}; #[test] fn test_stringify() { diff --git a/src/request.rs b/src/request.rs index 17fdf338..97832857 100644 --- a/src/request.rs +++ b/src/request.rs @@ -1,18 +1,22 @@ -use std::any::Any; -use std::collections::HashMap; -use std::fmt::{self, Debug, Formatter}; +use std::{ + any::Any, + collections::HashMap, + fmt::{self, Debug, Formatter}, +}; use serde::{Deserialize, Deserializer, Serialize}; -use crate::parser::parse_query; -use crate::parser::types::ExecutableDocument; -use crate::schema::IntrospectionMode; -use crate::{Data, ParseRequestError, ServerError, UploadValue, Value, Variables}; +use crate::{ + parser::{parse_query, types::ExecutableDocument}, + schema::IntrospectionMode, + Data, ParseRequestError, ServerError, UploadValue, Value, Variables, +}; /// GraphQL request. /// -/// This can be deserialized from a structure of the query string, the operation name and the -/// variables. The names are all in `camelCase` (e.g. `operationName`). +/// This can be deserialized from a structure of the query string, the operation +/// name and the variables. The names are all in `camelCase` (e.g. +/// `operationName`). #[non_exhaustive] #[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -45,14 +49,16 @@ pub struct Request { /// Disable introspection queries for this request. /// This option has priority over `introspection_mode` when set to true. - /// `introspection_mode` has priority when `disable_introspection` set to `false`. + /// `introspection_mode` has priority when `disable_introspection` set to + /// `false`. #[serde(skip)] pub disable_introspection: bool, #[serde(skip)] pub(crate) parsed_query: Option, - /// Sets the introspection mode for this request (defaults to [IntrospectionMode::Enabled]). + /// Sets the introspection mode for this request (defaults to + /// [IntrospectionMode::Enabled]). #[serde(skip)] pub introspection_mode: IntrospectionMode, } @@ -114,8 +120,8 @@ impl Request { #[inline] /// Performs parsing of query ahead of execution. /// - /// This effectively allows to inspect query information, before passing request to schema for - /// execution as long as query is valid. + /// This effectively allows to inspect query information, before passing + /// request to schema for execution as long as query is valid. pub fn parsed_query(&mut self) -> Result<&ExecutableDocument, ServerError> { if self.parsed_query.is_none() { match parse_query(&self.query) { @@ -124,17 +130,17 @@ impl Request { } } - //forbid_unsafe effectively bans optimize away else branch here so use unwrap - //but this unwrap never panics + // forbid_unsafe effectively bans optimize away else branch here so use unwrap + // but this unwrap never panics Ok(self.parsed_query.as_ref().unwrap()) } /// Set a variable to an upload value. /// - /// `var_path` is a dot-separated path to the item that begins with `variables`, for example - /// `variables.files.2.content` is equivalent to the Rust code - /// `request.variables["files"][2]["content"]`. If no variable exists at the path this function - /// won't do anything. + /// `var_path` is a dot-separated path to the item that begins with + /// `variables`, for example `variables.files.2.content` is equivalent + /// to the Rust code `request.variables["files"][2]["content"]`. If no + /// variable exists at the path this function won't do anything. pub fn set_upload(&mut self, var_path: &str, upload: UploadValue) { fn variable_path<'a>(variables: &'a mut Variables, path: &str) -> Option<&'a mut Value> { let mut parts = path.strip_prefix("variables.")?.split('.'); @@ -178,12 +184,13 @@ impl Debug for Request { } } -/// Batch support for GraphQL requests, which is either a single query, or an array of queries +/// Batch support for GraphQL requests, which is either a single query, or an +/// array of queries /// /// **Reference:** #[derive(Debug, Deserialize)] #[serde(untagged)] -#[allow(clippy::large_enum_variant)] //Request is at fault +#[allow(clippy::large_enum_variant)] // Request is at fault pub enum BatchRequest { /// Single query Single(Request), @@ -198,8 +205,8 @@ impl BatchRequest { /// /// # Errors /// - /// Fails if the batch request is a list of requests with a message saying that batch requests - /// aren't supported. + /// Fails if the batch request is a list of requests with a message saying + /// that batch requests aren't supported. pub fn into_single(self) -> Result { match self { Self::Single(req) => Ok(req), diff --git a/src/resolver_utils/container.rs b/src/resolver_utils/container.rs index dd9cf214..ae68f0f0 100644 --- a/src/resolver_utils/container.rs +++ b/src/resolver_utils/container.rs @@ -1,21 +1,17 @@ -use futures_util::FutureExt; -use std::future::Future; -use std::pin::Pin; -use std::sync::Arc; +use std::{future::Future, pin::Pin, sync::Arc}; +use futures_util::FutureExt; use indexmap::IndexMap; -use crate::extensions::ResolveInfo; -use crate::parser::types::Selection; use crate::{ - Context, ContextBase, ContextSelectionSet, Error, Name, OutputType, ServerError, ServerResult, - Value, + extensions::ResolveInfo, parser::types::Selection, Context, ContextBase, ContextSelectionSet, + Error, Name, OutputType, ServerError, ServerResult, Value, }; /// Represents a GraphQL container object. /// -/// This helper trait allows the type to call `resolve_container` on itself in its -/// `OutputType::resolve` implementation. +/// This helper trait allows the type to call `resolve_container` on itself in +/// its `OutputType::resolve` implementation. #[async_trait::async_trait] pub trait ContainerType: OutputType { /// This function returns true of type `EmptyMutation` only. @@ -24,15 +20,17 @@ pub trait ContainerType: OutputType { false } - /// Resolves a field value and outputs it as a json value `async_graphql::Value`. + /// Resolves a field value and outputs it as a json value + /// `async_graphql::Value`. /// /// If the field was not found returns None. async fn resolve_field(&self, ctx: &Context<'_>) -> ServerResult>; - /// Collect all the fields of the container that are queried in the selection set. + /// Collect all the fields of the container that are queried in the + /// selection set. /// - /// Objects do not have to override this, but interfaces and unions must call it on their - /// internal type. + /// Objects do not have to override this, but interfaces and unions must + /// call it on their internal type. fn collect_all_fields<'a>( &'a self, ctx: &ContextSelectionSet<'a>, @@ -175,7 +173,8 @@ type BoxFieldFuture<'a> = Pin(Vec>); impl<'a> Fields<'a> { - /// Add another set of fields to this set of fields using the given container. + /// Add another set of fields to this set of fields using the given + /// container. pub fn add_set( &mut self, ctx: &ContextSelectionSet<'a>, diff --git a/src/resolver_utils/enum.rs b/src/resolver_utils/enum.rs index b2dc5c28..8f8d6de5 100644 --- a/src/resolver_utils/enum.rs +++ b/src/resolver_utils/enum.rs @@ -38,7 +38,8 @@ pub fn parse_enum(value: Value) -> InputValueResult /// Convert the enum value into a GraphQL value. /// -/// This can be used to implement `InputType::to_value` or `OutputType::resolve`. +/// This can be used to implement `InputType::to_value` or +/// `OutputType::resolve`. pub fn enum_value(value: T) -> Value { let item = T::items().iter().find(|item| item.value == value).unwrap(); Value::Enum(Name::new(item.name)) diff --git a/src/resolver_utils/list.rs b/src/resolver_utils/list.rs index 641ebdd9..be61f41f 100644 --- a/src/resolver_utils/list.rs +++ b/src/resolver_utils/list.rs @@ -1,6 +1,7 @@ -use crate::extensions::ResolveInfo; -use crate::parser::types::Field; -use crate::{ContextSelectionSet, OutputType, Positioned, ServerResult, Value}; +use crate::{ + extensions::ResolveInfo, parser::types::Field, ContextSelectionSet, OutputType, Positioned, + ServerResult, Value, +}; /// Resolve an list by executing each of the items concurrently. pub async fn resolve_list<'a, T: OutputType + 'a>( diff --git a/src/resolver_utils/scalar.rs b/src/resolver_utils/scalar.rs index 85dd9c27..e46538f7 100644 --- a/src/resolver_utils/scalar.rs +++ b/src/resolver_utils/scalar.rs @@ -33,7 +33,8 @@ pub trait ScalarType: Sized + Send { /// Checks for a valid scalar value. /// - /// Implementing this function can find incorrect input values during the verification phase, which can improve performance. + /// Implementing this function can find incorrect input values during the + /// verification phase, which can improve performance. fn is_valid(_value: &Value) -> bool { true } @@ -44,8 +45,11 @@ pub trait ScalarType: Sized + Send { /// Define a scalar /// -/// If your type implemented `serde::Serialize` and `serde::Deserialize`, then you can use this macro to define a scalar more simply. -/// It helps you implement the `ScalarType::parse` and `ScalarType::to_value` functions by calling the [from_value](fn.from_value.html) and [to_value](fn.to_value.html) functions. +/// If your type implemented `serde::Serialize` and `serde::Deserialize`, then +/// you can use this macro to define a scalar more simply. It helps you +/// implement the `ScalarType::parse` and `ScalarType::to_value` functions by +/// calling the [from_value](fn.from_value.html) and +/// [to_value](fn.to_value.html) functions. /// /// # Examples /// diff --git a/src/response.rs b/src/response.rs index e8bcd134..0be1705a 100644 --- a/src/response.rs +++ b/src/response.rs @@ -1,7 +1,9 @@ use std::collections::BTreeMap; -use http::header::{HeaderMap, HeaderName}; -use http::HeaderValue; +use http::{ + header::{HeaderMap, HeaderName}, + HeaderValue, +}; use serde::{Deserialize, Serialize}; use crate::{CacheControl, Result, ServerError, Value}; @@ -87,8 +89,8 @@ impl Response { !self.is_ok() } - /// Extract the error from the response. Only if the `error` field is empty will this return - /// `Ok`. + /// Extract the error from the response. Only if the `error` field is empty + /// will this return `Ok`. #[inline] pub fn into_result(self) -> Result> { if self.is_err() { diff --git a/src/schema.rs b/src/schema.rs index 93fb7fe4..602ebab7 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -1,28 +1,26 @@ -use std::any::Any; -use std::collections::HashMap; -use std::ops::Deref; -use std::sync::Arc; +use std::{any::Any, collections::HashMap, ops::Deref, sync::Arc}; use futures_util::stream::{self, Stream, StreamExt}; use indexmap::map::IndexMap; -use crate::custom_directive::CustomDirectiveFactory; -use crate::extensions::{ExtensionFactory, Extensions}; -use crate::model::__DirectiveLocation; -use crate::parser::types::{Directive, DocumentOperations, OperationType, Selection, SelectionSet}; -use crate::parser::{parse_query, Positioned}; -use crate::registry::{MetaDirective, MetaInputValue, Registry}; -use crate::resolver_utils::{resolve_container, resolve_container_serial}; -use crate::subscription::collect_subscription_streams; -use crate::types::QueryRoot; -use crate::validation::{check_rules, ValidationMode}; use crate::{ context::{Data, QueryEnvInner}, - EmptyMutation, EmptySubscription, -}; -use crate::{ - BatchRequest, BatchResponse, CacheControl, ContextBase, InputType, ObjectType, OutputType, - QueryEnv, Request, Response, ServerError, SubscriptionType, Variables, ID, + custom_directive::CustomDirectiveFactory, + extensions::{ExtensionFactory, Extensions}, + model::__DirectiveLocation, + parser::{ + parse_query, + types::{Directive, DocumentOperations, OperationType, Selection, SelectionSet}, + Positioned, + }, + registry::{MetaDirective, MetaInputValue, Registry}, + resolver_utils::{resolve_container, resolve_container_serial}, + subscription::collect_subscription_streams, + types::QueryRoot, + validation::{check_rules, ValidationMode}, + BatchRequest, BatchResponse, CacheControl, ContextBase, EmptyMutation, EmptySubscription, + InputType, ObjectType, OutputType, QueryEnv, Request, Response, ServerError, SubscriptionType, + Variables, ID, }; /// Introspection mode @@ -56,7 +54,8 @@ pub struct SchemaBuilder { impl SchemaBuilder { /// Manually register a input type in the schema. /// - /// You can use this function to register schema types that are not directly referenced. + /// You can use this function to register schema types that are not directly + /// referenced. #[must_use] pub fn register_input_type(mut self) -> Self { T::create_type_info(&mut self.registry); @@ -65,7 +64,8 @@ impl SchemaBuilder /// Manually register a output type in the schema. /// - /// You can use this function to register schema types that are not directly referenced. + /// You can use this function to register schema types that are not directly + /// referenced. #[must_use] pub fn register_output_type(mut self) -> Self { T::create_type_info(&mut self.registry); @@ -79,14 +79,16 @@ impl SchemaBuilder self } - /// Only process introspection queries, everything else is processed as an error. + /// Only process introspection queries, everything else is processed as an + /// error. #[must_use] pub fn introspection_only(mut self) -> Self { self.registry.introspection_mode = IntrospectionMode::IntrospectionOnly; self } - /// Set the maximum complexity a query can have. By default, there is no limit. + /// Set the maximum complexity a query can have. By default, there is no + /// limit. #[must_use] pub fn limit_complexity(mut self, complexity: usize) -> Self { self.complexity = Some(complexity); @@ -116,7 +118,7 @@ impl SchemaBuilder /// } /// } /// - /// let schema = Schema::build(Query, EmptyMutation,EmptySubscription) + /// let schema = Schema::build(Query, EmptyMutation, EmptySubscription) /// .extension(extensions::Logger) /// .finish(); /// ``` @@ -126,7 +128,8 @@ impl SchemaBuilder self } - /// Add a global data that can be accessed in the `Schema`. You access it with `Context::data`. + /// Add a global data that can be accessed in the `Schema`. You access it + /// with `Context::data`. #[must_use] pub fn data(mut self, data: D) -> Self { self.data.insert(data); @@ -140,7 +143,8 @@ impl SchemaBuilder self } - /// Enable federation, which is automatically enabled if the Query has least one entity definition. + /// Enable federation, which is automatically enabled if the Query has least + /// one entity definition. #[must_use] pub fn enable_federation(mut self) -> Self { self.registry.enable_federation = true; @@ -149,7 +153,8 @@ impl SchemaBuilder /// Make the Federation SDL include subscriptions. /// - /// Note: Not included by default, in order to be compatible with Apollo Server. + /// Note: Not included by default, in order to be compatible with Apollo + /// Server. #[must_use] pub fn enable_subscription_in_federation(mut self) -> Self { self.registry.federation_subscription = true; @@ -426,9 +431,10 @@ where /// Get all names in this schema /// - /// Maybe you want to serialize a custom binary protocol. In order to minimize message size, a dictionary - /// is usually used to compress type names, field names, directive names, and parameter names. This function gets all the names, - /// so you can create this dictionary. + /// Maybe you want to serialize a custom binary protocol. In order to + /// minimize message size, a dictionary is usually used to compress type + /// names, field names, directive names, and parameter names. This function + /// gets all the names, so you can create this dictionary. pub fn names(&self) -> Vec { self.0.env.registry.names() } diff --git a/src/subscription.rs b/src/subscription.rs index 7257a7e9..4863c16b 100644 --- a/src/subscription.rs +++ b/src/subscription.rs @@ -1,12 +1,12 @@ -use std::borrow::Cow; -use std::pin::Pin; +use std::{borrow::Cow, pin::Pin}; use futures_util::stream::{Stream, StreamExt}; -use crate::parser::types::{Selection, TypeCondition}; -use crate::registry::Registry; use crate::{ - registry, Context, ContextSelectionSet, PathSegment, Response, ServerError, ServerResult, + parser::types::{Selection, TypeCondition}, + registry, + registry::Registry, + Context, ContextSelectionSet, PathSegment, Response, ServerError, ServerResult, }; /// A GraphQL subscription object diff --git a/src/types/any.rs b/src/types/any.rs index 02fbb65b..738a1f7b 100644 --- a/src/types/any.rs +++ b/src/types/any.rs @@ -2,11 +2,13 @@ use crate::{InputValueResult, Scalar, ScalarType, Value}; /// Any scalar (For [Apollo Federation](https://www.apollographql.com/docs/apollo-server/federation/introduction)) /// -/// The `Any` scalar is used to pass representations of entities from external services into the root `_entities` field for execution. +/// The `Any` scalar is used to pass representations of entities from external +/// services into the root `_entities` field for execution. #[derive(Clone, PartialEq, Debug)] pub struct Any(pub Value); -/// The `_Any` scalar is used to pass representations of entities from external services into the root `_entities` field for execution. +/// The `_Any` scalar is used to pass representations of entities from external +/// services into the root `_entities` field for execution. #[Scalar(internal, name = "_Any")] impl ScalarType for Any { fn parse(value: Value) -> InputValueResult { diff --git a/src/types/connection/connection_type.rs b/src/types/connection/connection_type.rs index e17c8340..1be0f889 100644 --- a/src/types/connection/connection_type.rs +++ b/src/types/connection/connection_type.rs @@ -1,34 +1,56 @@ -use std::borrow::Cow; +use std::{borrow::Cow, marker::PhantomData}; -use futures_util::stream::{Stream, StreamExt, TryStreamExt}; -use indexmap::map::IndexMap; - -use crate::connection::edge::Edge; -use crate::connection::page_info::PageInfo; -use crate::parser::types::Field; -use crate::registry::MetaTypeId; -use crate::resolver_utils::{resolve_container, ContainerType}; -use crate::types::connection::{CursorType, EmptyFields}; use crate::{ - registry, Context, ContextSelectionSet, ObjectType, OutputType, Positioned, Result, - ServerResult, Value, + connection::{edge::Edge, ConnectionNameType, EdgeNameType, PageInfo}, + types::connection::{CursorType, EmptyFields}, + Object, ObjectType, OutputType, TypeName, }; /// Connection type /// /// Connection is the result of a query for `connection::query`. -pub struct Connection { +pub struct Connection< + Name, + EdgeName, + Cursor, + Node, + ConnectionFields = EmptyFields, + EdgeFields = EmptyFields, +> where + Name: ConnectionNameType, + EdgeName: EdgeNameType, + Cursor: CursorType + Send + Sync, + Node: OutputType, + ConnectionFields: ObjectType, + EdgeFields: ObjectType, +{ + _mark1: PhantomData, + _mark2: PhantomData, /// All edges of the current page. - pub edges: Vec>, - additional_fields: EC, - has_previous_page: bool, - has_next_page: bool, + pub edges: Vec>, + /// Additional fields for connection object. + pub additional_fields: ConnectionFields, + /// If `true` means has previous page. + pub has_previous_page: bool, + /// If `false` means has next page. + pub has_next_page: bool, } -impl Connection { +impl + Connection +where + Name: ConnectionNameType, + EdgeName: EdgeNameType, + Cursor: CursorType + Send + Sync, + Node: OutputType, + EdgeFields: ObjectType, +{ /// Create a new connection. + #[inline] pub fn new(has_previous_page: bool, has_next_page: bool) -> Self { Connection { + _mark1: PhantomData, + _mark2: PhantomData, additional_fields: EmptyFields, has_previous_page, has_next_page, @@ -37,14 +59,26 @@ impl Connection { } } -impl Connection { +impl + Connection +where + Name: ConnectionNameType, + EdgeName: EdgeNameType, + Cursor: CursorType + Send + Sync, + Node: OutputType, + ConnectionFields: ObjectType, + EdgeFields: ObjectType, +{ /// Create a new connection, it can have some additional fields. + #[inline] pub fn with_additional_fields( has_previous_page: bool, has_next_page: bool, - additional_fields: EC, + additional_fields: ConnectionFields, ) -> Self { Connection { + _mark1: PhantomData, + _mark2: PhantomData, additional_fields, has_previous_page, has_next_page, @@ -53,198 +87,52 @@ impl Connection { } } -impl Connection { - /// Convert the edge type and return a new `Connection`. - pub fn map(self, mut f: F) -> Connection - where - F: FnMut(Edge) -> Edge, - { - let mut new_edges = Vec::with_capacity(self.edges.len()); - for edge in self.edges { - new_edges.push(f(edge)); - } - Connection { - edges: new_edges, - additional_fields: self.additional_fields, +#[Object(internal, name_type)] +impl + Connection +where + Name: ConnectionNameType, + EdgeName: EdgeNameType, + Cursor: CursorType + Send + Sync, + Node: OutputType, + ConnectionFields: ObjectType, + EdgeFields: ObjectType, +{ + /// Information to aid in pagination. + async fn page_info(&self) -> PageInfo { + PageInfo { has_previous_page: self.has_previous_page, has_next_page: self.has_next_page, + start_cursor: self.edges.first().map(|edge| edge.cursor.0.encode_cursor()), + end_cursor: self.edges.last().map(|edge| edge.cursor.0.encode_cursor()), } } - /// Convert the node type and return a new `Connection`. - pub fn map_node(self, mut f: F) -> Connection - where - F: FnMut(T) -> T2, - { - self.map(|edge| Edge { - cursor: edge.cursor, - node: f(edge.node), - additional_fields: edge.additional_fields, - }) + /// A list of edges. + #[inline] + async fn edges(&self) -> &[Edge] { + &self.edges } - /// Append edges with `IntoIterator>` - pub fn append(&mut self, iter: I) - where - I: IntoIterator>, - { - self.edges.extend(iter); - } - - /// Append edges with `IntoIterator, E>>` - pub fn try_append(&mut self, iter: I) -> Result<(), E> - where - I: IntoIterator, E>>, - { - for edge in iter { - self.edges.push(edge?); - } - Ok(()) - } - - /// Append edges with `Stream>>` - pub async fn append_stream(&mut self, stream: S) - where - S: Stream> + Unpin, - { - self.edges.extend(stream.collect::>().await); - } - - /// Append edges with `Stream, E>>` - pub async fn try_append_stream(&mut self, stream: S) -> Result<(), E> - where - S: Stream, E>> + Unpin, - { - self.edges.extend(stream.try_collect::>().await?); - Ok(()) + #[graphql(flatten)] + #[inline] + async fn additional_fields(&self) -> &ConnectionFields { + &self.additional_fields } } -#[async_trait::async_trait] -impl ContainerType for Connection +impl TypeName + for Connection where - C: CursorType + Send + Sync, - T: OutputType, - EC: ObjectType, - EE: ObjectType, -{ - async fn resolve_field(&self, ctx: &Context<'_>) -> ServerResult> { - if ctx.item.node.name.node == "pageInfo" { - let page_info = PageInfo { - has_previous_page: self.has_previous_page, - has_next_page: self.has_next_page, - start_cursor: self.edges.first().map(|edge| edge.cursor.encode_cursor()), - end_cursor: self.edges.last().map(|edge| edge.cursor.encode_cursor()), - }; - let ctx_obj = ctx.with_selection_set(&ctx.item.node.selection_set); - return OutputType::resolve(&page_info, &ctx_obj, ctx.item) - .await - .map(Some); - } else if ctx.item.node.name.node == "edges" { - let ctx_obj = ctx.with_selection_set(&ctx.item.node.selection_set); - return OutputType::resolve(&self.edges, &ctx_obj, ctx.item) - .await - .map(Some); - } - - self.additional_fields.resolve_field(ctx).await - } -} - -#[async_trait::async_trait] -impl OutputType for Connection -where - C: CursorType + Send + Sync, - T: OutputType, - EC: ObjectType, - EE: ObjectType, + Name: ConnectionNameType, + EdgeName: EdgeNameType, + Cursor: CursorType + Send + Sync, + Node: OutputType, + ConnectionFields: ObjectType, + EdgeFields: ObjectType, { + #[inline] fn type_name() -> Cow<'static, str> { - Cow::Owned(format!("{}Connection", T::type_name())) - } - - fn create_type_info(registry: &mut registry::Registry) -> String { - registry.create_output_type::(MetaTypeId::Object,|registry| { - EC::create_type_info(registry); - let additional_fields = if let Some(registry::MetaType::Object { fields, .. }) = - registry.types.remove(EC::type_name().as_ref()) - { - fields - } else { - unreachable!() - }; - - registry::MetaType::Object { - name: Self::type_name().to_string(), - description: None, - fields: { - let mut fields = IndexMap::new(); - - fields.insert( - "pageInfo".to_string(), - registry::MetaField { - name: "pageInfo".to_string(), - description: Some("Information to aid in pagination."), - args: Default::default(), - ty: PageInfo::create_type_info(registry), - deprecation: Default::default(), - cache_control: Default::default(), - external: false, - requires: None, - provides: None, - visible: None, - compute_complexity: None, - oneof: false, - }, - ); - - fields.insert( - "edges".to_string(), - registry::MetaField { - name: "edges".to_string(), - description: Some("A list of edges."), - args: Default::default(), - ty: >>> as OutputType>::create_type_info( - registry, - ), - deprecation: Default::default(), - cache_control: Default::default(), - external: false, - requires: None, - provides: None, - visible: None, - compute_complexity: None, - oneof: false, - }, - ); - - fields.extend(additional_fields); - fields - }, - cache_control: Default::default(), - extends: false, - keys: None, - visible: None, - is_subscription: false, - rust_typename: std::any::type_name::(), - } - }) - } - - async fn resolve( - &self, - ctx: &ContextSelectionSet<'_>, - _field: &Positioned, - ) -> ServerResult { - resolve_container(ctx, self).await + Name::type_name::().into() } } - -impl ObjectType for Connection -where - C: CursorType + Send + Sync, - T: OutputType, - EC: ObjectType, - EE: ObjectType, -{ -} diff --git a/src/types/connection/cursor.rs b/src/types/connection/cursor.rs index fdb67319..e3319b78 100644 --- a/src/types/connection/cursor.rs +++ b/src/types/connection/cursor.rs @@ -1,6 +1,4 @@ -use std::convert::Infallible; -use std::fmt::Display; -use std::num::ParseIntError; +use std::{convert::Infallible, fmt::Display, num::ParseIntError}; use crate::ID; diff --git a/src/types/connection/edge.rs b/src/types/connection/edge.rs index 54f4660a..59b08a7d 100644 --- a/src/types/connection/edge.rs +++ b/src/types/connection/edge.rs @@ -1,155 +1,104 @@ -use std::borrow::Cow; +use std::{borrow::Cow, marker::PhantomData}; -use indexmap::map::IndexMap; - -use crate::connection::EmptyFields; -use crate::parser::types::Field; -use crate::registry::MetaTypeId; -use crate::resolver_utils::{resolve_container, ContainerType}; -use crate::types::connection::CursorType; use crate::{ - registry, Context, ContextSelectionSet, ObjectType, OutputType, Positioned, ServerResult, Value, + connection::EmptyFields, + types::connection::{CursorType, EdgeNameType}, + InputValueError, InputValueResult, ObjectType, OutputType, Scalar, ScalarType, SimpleObject, + TypeName, Value, }; -/// The edge type output by the data source -pub struct Edge { - pub(crate) cursor: C, - pub(crate) node: T, - pub(crate) additional_fields: E, +pub(crate) struct CursorScalar(pub(crate) T); + +#[Scalar(internal, name = "String")] +impl ScalarType for CursorScalar { + fn parse(value: Value) -> InputValueResult { + match value { + Value::String(s) => T::decode_cursor(&s) + .map(Self) + .map_err(InputValueError::custom), + _ => Err(InputValueError::expected_type(value)), + } + } + + fn is_valid(value: &Value) -> bool { + matches!(value, Value::String(_)) + } + + fn to_value(&self) -> Value { + Value::String(self.0.encode_cursor()) + } } -impl Edge { +/// An edge in a connection. +#[derive(SimpleObject)] +#[graphql(internal, name_type)] +pub struct Edge +where + Name: EdgeNameType, + Cursor: CursorType + Send + Sync, + Node: OutputType, + EdgeFields: ObjectType, +{ + #[graphql(skip)] + _mark: PhantomData, + /// A cursor for use in pagination + pub(crate) cursor: CursorScalar, + /// "The item at the end of the edge + pub(crate) node: Node, + #[graphql(flatten)] + pub(crate) additional_fields: EdgeFields, +} + +impl TypeName for Edge +where + Name: EdgeNameType, + Cursor: CursorType + Send + Sync, + Node: OutputType, + EdgeFields: ObjectType, +{ + #[inline] + fn type_name() -> Cow<'static, str> { + Name::type_name::().into() + } +} + +impl Edge +where + Name: EdgeNameType, + Cursor: CursorType + Send + Sync, + Node: OutputType, + EdgeFields: ObjectType, +{ /// Create a new edge, it can have some additional fields. - pub fn with_additional_fields(cursor: C, node: T, additional_fields: E) -> Self { + #[inline] + pub fn with_additional_fields( + cursor: Cursor, + node: Node, + additional_fields: EdgeFields, + ) -> Self { Self { - cursor, + _mark: PhantomData, + cursor: CursorScalar(cursor), node, additional_fields, } } } -impl Edge { +impl Edge +where + Name: EdgeNameType, + Cursor: CursorType + Send + Sync, + Node: OutputType, +{ /// Create a new edge. - pub fn new(cursor: C, node: T) -> Self { + #[inline] + pub fn new(cursor: Cursor, node: Node) -> Self { Self { - cursor, + _mark: PhantomData, + cursor: CursorScalar(cursor), node, additional_fields: EmptyFields, } } } - -#[async_trait::async_trait] -impl ContainerType for Edge -where - C: CursorType + Send + Sync, - T: OutputType, - E: ObjectType, -{ - async fn resolve_field(&self, ctx: &Context<'_>) -> ServerResult> { - if ctx.item.node.name.node == "node" { - let ctx_obj = ctx.with_selection_set(&ctx.item.node.selection_set); - return OutputType::resolve(&self.node, &ctx_obj, ctx.item) - .await - .map(Some); - } else if ctx.item.node.name.node == "cursor" { - return Ok(Some(Value::String(self.cursor.encode_cursor()))); - } - - self.additional_fields.resolve_field(ctx).await - } -} - -#[async_trait::async_trait] -impl OutputType for Edge -where - C: CursorType + Send + Sync, - T: OutputType, - E: ObjectType, -{ - fn type_name() -> Cow<'static, str> { - Cow::Owned(format!("{}Edge", T::type_name())) - } - - fn create_type_info(registry: &mut registry::Registry) -> String { - registry.create_output_type::(MetaTypeId::Object, |registry| { - let additional_fields = if let registry::MetaType::Object { fields, .. } = - registry.create_fake_output_type::() - { - fields - } else { - unreachable!() - }; - - registry::MetaType::Object { - name: Self::type_name().to_string(), - description: Some("An edge in a connection."), - fields: { - let mut fields = IndexMap::new(); - - fields.insert( - "node".to_string(), - registry::MetaField { - name: "node".to_string(), - description: Some("The item at the end of the edge"), - args: Default::default(), - ty: T::create_type_info(registry), - deprecation: Default::default(), - cache_control: Default::default(), - external: false, - requires: None, - provides: None, - visible: None, - compute_complexity: None, - oneof: false, - }, - ); - - fields.insert( - "cursor".to_string(), - registry::MetaField { - name: "cursor".to_string(), - description: Some("A cursor for use in pagination"), - args: Default::default(), - ty: String::create_type_info(registry), - deprecation: Default::default(), - cache_control: Default::default(), - external: false, - requires: None, - provides: None, - visible: None, - compute_complexity: None, - oneof: false, - }, - ); - - fields.extend(additional_fields); - fields - }, - cache_control: Default::default(), - extends: false, - keys: None, - visible: None, - is_subscription: false, - rust_typename: std::any::type_name::(), - } - }) - } - - async fn resolve( - &self, - ctx: &ContextSelectionSet<'_>, - _field: &Positioned, - ) -> ServerResult { - resolve_container(ctx, self).await - } -} - -impl ObjectType for Edge -where - C: CursorType + Send + Sync, - T: OutputType, - E: ObjectType, -{ -} diff --git a/src/types/connection/mod.rs b/src/types/connection/mod.rs index c4976bb3..94d71baa 100644 --- a/src/types/connection/mod.rs +++ b/src/types/connection/mod.rs @@ -5,26 +5,57 @@ mod cursor; mod edge; mod page_info; -use std::fmt::Display; -use std::future::Future; +use std::{fmt::Display, future::Future}; pub use connection_type::Connection; pub use cursor::CursorType; pub use edge::Edge; pub use page_info::PageInfo; -use crate::{Error, Result, SimpleObject}; +use crate::{Error, ObjectType, OutputType, Result, SimpleObject}; /// Empty additional fields #[derive(SimpleObject)] #[graphql(internal, fake)] pub struct EmptyFields; +/// Used to specify the edge name. +pub trait EdgeNameType: Send + Sync { + /// Returns the edge type name. + fn type_name() -> String; +} + +/// Name the edge type by default with the default format. +pub struct DefaultEdgeName; + +impl EdgeNameType for DefaultEdgeName { + fn type_name() -> String { + format!("{}Edge", T::type_name()) + } +} + +/// Used to specify the connection name. +pub trait ConnectionNameType: Send + Sync { + /// Returns the connection type name. + fn type_name() -> String; +} + +/// Name the connection type by default with the default format. +pub struct DefaultConnectionName; + +impl ConnectionNameType for DefaultConnectionName { + fn type_name() -> String { + format!("{}Connection", T::type_name()) + } +} + /// Parses the parameters and executes the query. /// /// # Examples /// /// ```rust +/// use std::borrow::Cow; +/// /// use async_graphql::*; /// use async_graphql::types::connection::*; /// @@ -44,7 +75,7 @@ pub struct EmptyFields; /// before: Option, /// first: Option, /// last: Option -/// ) -> Result> { +/// ) -> Result> { /// query(after, before, first, last, |after, before, first, last| async move { /// let mut start = after.map(|after| after + 1).unwrap_or(0); /// let mut end = before.unwrap_or(10000); @@ -59,7 +90,7 @@ pub struct EmptyFields; /// }; /// } /// let mut connection = Connection::new(start > 0, end < 10000); -/// connection.append( +/// connection.edges.extend( /// (start..end).into_iter().map(|n| /// Edge::with_additional_fields(n, n as i32, Diff{ diff: (10000 - n) as i32 })), /// ); @@ -90,31 +121,108 @@ pub struct EmptyFields; /// })); /// # }); /// ``` -pub async fn query( +/// +/// # Custom connection and edge type names +/// +/// ``` +/// use async_graphql::{connection::*, *}; +/// +/// #[derive(SimpleObject)] +/// struct MyObj { +/// a: i32, +/// b: String, +/// } +/// +/// // Use to custom connection name +/// struct MyConnectionName; +/// +/// impl ConnectionNameType for MyConnectionName { +/// fn type_name() -> String { +/// "MyConnection".to_string() +/// } +/// } +/// +/// // Use to custom edge name +/// struct MyEdgeName; +/// +/// impl EdgeNameType for MyEdgeName { +/// fn type_name() -> String { +/// "MyEdge".to_string() +/// } +/// } +/// +/// struct Query; +/// +/// #[Object] +/// impl Query { +/// async fn numbers( +/// &self, +/// after: Option, +/// before: Option, +/// first: Option, +/// last: Option, +/// ) -> Connection { +/// let mut connection = Connection::new(false, false); +/// connection.edges.push(Edge::new(1, MyObj { a: 100, b: "abc".to_string() })); +/// connection +/// } +/// } +/// +/// # tokio::runtime::Runtime::new().unwrap().block_on(async { +/// let schema = Schema::new(Query, EmptyMutation, EmptySubscription); +/// +/// let query = r#"{ +/// numbers(first: 2) { +/// __typename +/// edges { __typename node { a b } } +/// } +/// }"#; +/// let data = schema.execute(query).await.into_result().unwrap().data; +/// assert_eq!(data, value!({ +/// "numbers": { +/// "__typename": "MyConnection", +/// "edges": [ +/// {"__typename": "MyEdge", "node": { "a": 100, "b": "abc" }}, +/// ] +/// }, +/// })); +/// # }); +/// ``` +pub async fn query( after: Option, before: Option, first: Option, last: Option, f: F, -) -> Result> +) -> Result> where + Name: ConnectionNameType, + EdgeName: EdgeNameType, Cursor: CursorType + Send + Sync, ::Error: Display + Send + Sync + 'static, + Node: OutputType, + ConnectionFields: ObjectType, + EdgeFields: ObjectType, F: FnOnce(Option, Option, Option, Option) -> R, - R: Future, E>>, + R: Future< + Output = Result, E>, + >, E: Into, { query_with(after, before, first, last, f).await } -/// Parses the parameters and executes the query and return a custom `Connection` type. +/// Parses the parameters and executes the query and return a custom +/// `Connection` type. /// -/// `Connection` and `Edge` have certain limitations. For example, you cannot customize -/// the name of the type, so you can use this function to execute the query and return a customized `Connection` type. +/// `Connection` and `Edge` have certain limitations. For example, you +/// cannot customize the name of the type, so you can use this function to +/// execute the query and return a customized `Connection` type. /// /// # Examples /// /// ```rust +/// /// use async_graphql::*; /// use async_graphql::types::connection::*; /// @@ -172,29 +280,27 @@ where /// } /// } /// -/// #[tokio::main] -/// async fn main() { -/// let schema = Schema::new(Query, EmptyMutation, EmptySubscription); +/// # tokio::runtime::Runtime::new().unwrap().block_on(async { +/// let schema = Schema::new(Query, EmptyMutation, EmptySubscription); /// -/// assert_eq!(schema.execute("{ numbers(first: 2) { edges { node diff } } }").await.into_result().unwrap().data, value!({ -/// "numbers": { -/// "edges": [ -/// {"node": 0, "diff": 10000}, -/// {"node": 1, "diff": 9999}, -/// ] -/// }, -/// })); -/// -/// assert_eq!(schema.execute("{ numbers(last: 2) { edges { node diff } } }").await.into_result().unwrap().data, value!({ -/// "numbers": { -/// "edges": [ -/// {"node": 9998, "diff": 2}, -/// {"node": 9999, "diff": 1}, -/// ] -/// }, -/// })); -/// } +/// assert_eq!(schema.execute("{ numbers(first: 2) { edges { node diff } } }").await.into_result().unwrap().data, value!({ +/// "numbers": { +/// "edges": [ +/// {"node": 0, "diff": 10000}, +/// {"node": 1, "diff": 9999}, +/// ] +/// }, +/// })); /// +/// assert_eq!(schema.execute("{ numbers(last: 2) { edges { node diff } } }").await.into_result().unwrap().data, value!({ +/// "numbers": { +/// "edges": [ +/// {"node": 9998, "diff": 2}, +/// {"node": 9999, "diff": 1}, +/// ] +/// }, +/// })); +/// # }); /// ``` pub async fn query_with( after: Option, diff --git a/src/types/empty_mutation.rs b/src/types/empty_mutation.rs index 16a684ce..8b913c87 100644 --- a/src/types/empty_mutation.rs +++ b/src/types/empty_mutation.rs @@ -1,16 +1,14 @@ use std::borrow::Cow; -use crate::parser::types::Field; -use crate::registry::MetaTypeId; -use crate::resolver_utils::ContainerType; use crate::{ - registry, Context, ContextSelectionSet, ObjectType, OutputType, Positioned, ServerError, - ServerResult, Value, + parser::types::Field, registry, registry::MetaTypeId, resolver_utils::ContainerType, Context, + ContextSelectionSet, ObjectType, OutputType, Positioned, ServerError, ServerResult, Value, }; /// Empty mutation /// -/// Only the parameters used to construct the Schema, representing an unconfigured mutation. +/// Only the parameters used to construct the Schema, representing an +/// unconfigured mutation. /// /// # Examples /// diff --git a/src/types/empty_subscription.rs b/src/types/empty_subscription.rs index 406a17ea..2c8a3d97 100644 --- a/src/types/empty_subscription.rs +++ b/src/types/empty_subscription.rs @@ -1,5 +1,4 @@ -use std::borrow::Cow; -use std::pin::Pin; +use std::{borrow::Cow, pin::Pin}; use futures_util::stream::{self, Stream}; @@ -7,7 +6,8 @@ use crate::{registry, Context, Response, ServerError, SubscriptionType}; /// Empty subscription /// -/// Only the parameters used to construct the Schema, representing an unconfigured subscription. +/// Only the parameters used to construct the Schema, representing an +/// unconfigured subscription. #[derive(Default, Copy, Clone)] pub struct EmptySubscription; diff --git a/src/types/external/bson.rs b/src/types/external/bson.rs index b48f931d..3f35cf4f 100644 --- a/src/types/external/bson.rs +++ b/src/types/external/bson.rs @@ -1,9 +1,8 @@ -use bson::{oid::ObjectId, Bson, Document}; - #[cfg(feature = "chrono")] use bson::DateTime as UtcDateTime; #[cfg(feature = "bson-uuid")] use bson::Uuid; +use bson::{oid::ObjectId, Bson, Document}; #[cfg(feature = "chrono")] use chrono::{DateTime, Utc}; diff --git a/src/types/external/char.rs b/src/types/external/char.rs index d29850b0..3c738f54 100644 --- a/src/types/external/char.rs +++ b/src/types/external/char.rs @@ -1,7 +1,8 @@ use crate::{InputValueError, InputValueResult, Scalar, ScalarType, Value}; /// The `Char` scalar type represents a unicode char. -/// The input and output values are a string, and there can only be one unicode character in this string. +/// The input and output values are a string, and there can only be one unicode +/// character in this string. #[Scalar(internal)] impl ScalarType for char { fn parse(value: Value) -> InputValueResult { diff --git a/src/types/external/cow.rs b/src/types/external/cow.rs index 535f8a5a..807851a0 100644 --- a/src/types/external/cow.rs +++ b/src/types/external/cow.rs @@ -29,9 +29,10 @@ where #[cfg(test)] mod test { - use crate::*; use std::borrow::Cow; + use crate::*; + #[tokio::test] async fn test_cow_type() { struct Query { diff --git a/src/types/external/json_object/btreemap.rs b/src/types/external/json_object/btreemap.rs index 221e78d1..16328ea9 100644 --- a/src/types/external/json_object/btreemap.rs +++ b/src/types/external/json_object/btreemap.rs @@ -1,17 +1,12 @@ -use std::borrow::Cow; -use std::collections::BTreeMap; -use std::fmt::Display; -use std::str::FromStr; +use std::{borrow::Cow, collections::BTreeMap, fmt::Display, str::FromStr}; -use async_graphql_parser::types::Field; -use async_graphql_parser::Positioned; +use async_graphql_parser::{types::Field, Positioned}; use async_graphql_value::{from_value, to_value}; use indexmap::IndexMap; -use serde::de::DeserializeOwned; -use serde::Serialize; +use serde::{de::DeserializeOwned, Serialize}; -use crate::registry::{MetaType, MetaTypeId, Registry}; use crate::{ + registry::{MetaType, MetaTypeId, Registry}, ContextSelectionSet, InputType, InputValueError, InputValueResult, Name, OutputType, ServerResult, Value, }; diff --git a/src/types/external/json_object/hashbrown_hashmap.rs b/src/types/external/json_object/hashbrown_hashmap.rs index cf7ce7e0..6d914865 100644 --- a/src/types/external/json_object/hashbrown_hashmap.rs +++ b/src/types/external/json_object/hashbrown_hashmap.rs @@ -1,21 +1,16 @@ -use std::borrow::Cow; -use std::fmt::Display; -use std::hash::Hash; -use std::str::FromStr; +use std::{ + borrow::Cow, collections::HashMap as StdHashMap, fmt::Display, hash::Hash, str::FromStr, +}; -use async_graphql_parser::types::Field; -use async_graphql_parser::Positioned; +use async_graphql_parser::{types::Field, Positioned}; use async_graphql_value::{from_value, to_value}; use hashbrown::HashMap; use indexmap::IndexMap; -use serde::de::DeserializeOwned; -use serde::Serialize; -use std::collections::HashMap as StdHashMap; +use serde::{de::DeserializeOwned, Serialize}; -use crate::registry::Registry; use crate::{ - ContextSelectionSet, InputType, InputValueError, InputValueResult, Name, OutputType, - ServerResult, Value, + registry::Registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, Name, + OutputType, ServerResult, Value, }; impl InputType for HashMap diff --git a/src/types/external/json_object/hashmap.rs b/src/types/external/json_object/hashmap.rs index 1df5caf9..2725fa82 100644 --- a/src/types/external/json_object/hashmap.rs +++ b/src/types/external/json_object/hashmap.rs @@ -1,18 +1,18 @@ -use std::borrow::Cow; -use std::collections::HashMap; -use std::fmt::Display; -use std::hash::{BuildHasher, Hash}; -use std::str::FromStr; +use std::{ + borrow::Cow, + collections::HashMap, + fmt::Display, + hash::{BuildHasher, Hash}, + str::FromStr, +}; -use async_graphql_parser::types::Field; -use async_graphql_parser::Positioned; +use async_graphql_parser::{types::Field, Positioned}; use async_graphql_value::{from_value, to_value}; use indexmap::IndexMap; -use serde::de::DeserializeOwned; -use serde::Serialize; +use serde::{de::DeserializeOwned, Serialize}; -use crate::registry::{MetaType, MetaTypeId, Registry}; use crate::{ + registry::{MetaType, MetaTypeId, Registry}, ContextSelectionSet, InputType, InputValueError, InputValueResult, Name, OutputType, ServerResult, Value, }; diff --git a/src/types/external/list/array.rs b/src/types/external/list/array.rs index 8237bc22..4093af02 100644 --- a/src/types/external/list/array.rs +++ b/src/types/external/list/array.rs @@ -1,10 +1,8 @@ use std::borrow::Cow; -use crate::parser::types::Field; -use crate::resolver_utils::resolve_list; use crate::{ - registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, OutputType, - Positioned, ServerResult, Value, + parser::types::Field, registry, resolver_utils::resolve_list, ContextSelectionSet, InputType, + InputValueError, InputValueResult, OutputType, Positioned, ServerResult, Value, }; impl InputType for [T; N] { diff --git a/src/types/external/list/btree_set.rs b/src/types/external/list/btree_set.rs index 2e844e2a..8dbc7d0e 100644 --- a/src/types/external/list/btree_set.rs +++ b/src/types/external/list/btree_set.rs @@ -1,11 +1,8 @@ -use std::borrow::Cow; -use std::collections::BTreeSet; +use std::{borrow::Cow, collections::BTreeSet}; -use crate::parser::types::Field; -use crate::resolver_utils::resolve_list; use crate::{ - registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, OutputType, - Positioned, ServerResult, Value, + parser::types::Field, registry, resolver_utils::resolve_list, ContextSelectionSet, InputType, + InputValueError, InputValueResult, OutputType, Positioned, ServerResult, Value, }; impl InputType for BTreeSet { diff --git a/src/types/external/list/hash_set.rs b/src/types/external/list/hash_set.rs index 7a9a42c3..9473a0e1 100644 --- a/src/types/external/list/hash_set.rs +++ b/src/types/external/list/hash_set.rs @@ -1,13 +1,8 @@ -use std::borrow::Cow; -use std::cmp::Eq; -use std::collections::HashSet; -use std::hash::Hash; +use std::{borrow::Cow, cmp::Eq, collections::HashSet, hash::Hash}; -use crate::parser::types::Field; -use crate::resolver_utils::resolve_list; use crate::{ - registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, OutputType, - Positioned, Result, ServerResult, Value, + parser::types::Field, registry, resolver_utils::resolve_list, ContextSelectionSet, InputType, + InputValueError, InputValueResult, OutputType, Positioned, Result, ServerResult, Value, }; impl InputType for HashSet { diff --git a/src/types/external/list/hashbrown_hash_set.rs b/src/types/external/list/hashbrown_hash_set.rs index 22d89b00..f49b3c94 100644 --- a/src/types/external/list/hashbrown_hash_set.rs +++ b/src/types/external/list/hashbrown_hash_set.rs @@ -1,15 +1,10 @@ -use std::borrow::Cow; -use std::cmp::Eq; -use std::collections::HashSet as StdHashSet; -use std::hash::Hash; +use std::{borrow::Cow, cmp::Eq, collections::HashSet as StdHashSet, hash::Hash}; use hashbrown::HashSet; -use crate::parser::types::Field; -use crate::resolver_utils::resolve_list; use crate::{ - registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, OutputType, - Positioned, Result, ServerResult, Value, + parser::types::Field, registry, resolver_utils::resolve_list, ContextSelectionSet, InputType, + InputValueError, InputValueResult, OutputType, Positioned, Result, ServerResult, Value, }; impl InputType for HashSet { diff --git a/src/types/external/list/linked_list.rs b/src/types/external/list/linked_list.rs index bb99011f..ac13cf55 100644 --- a/src/types/external/list/linked_list.rs +++ b/src/types/external/list/linked_list.rs @@ -1,11 +1,8 @@ -use std::borrow::Cow; -use std::collections::LinkedList; +use std::{borrow::Cow, collections::LinkedList}; -use crate::parser::types::Field; -use crate::resolver_utils::resolve_list; use crate::{ - registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, OutputType, - Positioned, ServerResult, Value, + parser::types::Field, registry, resolver_utils::resolve_list, ContextSelectionSet, InputType, + InputValueError, InputValueResult, OutputType, Positioned, ServerResult, Value, }; impl InputType for LinkedList { diff --git a/src/types/external/list/slice.rs b/src/types/external/list/slice.rs index edf00be5..016d7c31 100644 --- a/src/types/external/list/slice.rs +++ b/src/types/external/list/slice.rs @@ -1,11 +1,8 @@ -use std::borrow::Cow; -use std::sync::Arc; +use std::{borrow::Cow, sync::Arc}; -use crate::parser::types::Field; -use crate::resolver_utils::resolve_list; use crate::{ - registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, OutputType, - Positioned, ServerResult, Value, + parser::types::Field, registry, resolver_utils::resolve_list, ContextSelectionSet, InputType, + InputValueError, InputValueResult, OutputType, Positioned, ServerResult, Value, }; #[async_trait::async_trait] diff --git a/src/types/external/list/vec.rs b/src/types/external/list/vec.rs index 9ab6a0ef..39d49ffa 100644 --- a/src/types/external/list/vec.rs +++ b/src/types/external/list/vec.rs @@ -1,10 +1,8 @@ use std::borrow::Cow; -use crate::parser::types::Field; -use crate::resolver_utils::resolve_list; use crate::{ - registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, OutputType, - Positioned, Result, ServerResult, Value, + parser::types::Field, registry, resolver_utils::resolve_list, ContextSelectionSet, InputType, + InputValueError, InputValueResult, OutputType, Positioned, Result, ServerResult, Value, }; impl InputType for Vec { diff --git a/src/types/external/list/vec_deque.rs b/src/types/external/list/vec_deque.rs index 131d27ff..c94549a0 100644 --- a/src/types/external/list/vec_deque.rs +++ b/src/types/external/list/vec_deque.rs @@ -1,11 +1,8 @@ -use std::borrow::Cow; -use std::collections::VecDeque; +use std::{borrow::Cow, collections::VecDeque}; -use crate::parser::types::Field; -use crate::resolver_utils::resolve_list; use crate::{ - registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, OutputType, - Positioned, ServerResult, Value, + parser::types::Field, registry, resolver_utils::resolve_list, ContextSelectionSet, InputType, + InputValueError, InputValueResult, OutputType, Positioned, ServerResult, Value, }; impl InputType for VecDeque { diff --git a/src/types/external/optional.rs b/src/types/external/optional.rs index 5643fe20..84043b81 100644 --- a/src/types/external/optional.rs +++ b/src/types/external/optional.rs @@ -1,9 +1,8 @@ use std::borrow::Cow; -use crate::parser::types::Field; use crate::{ - registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, OutputType, - Positioned, ServerResult, Value, + parser::types::Field, registry, ContextSelectionSet, InputType, InputValueError, + InputValueResult, OutputType, Positioned, ServerResult, Value, }; impl InputType for Option { diff --git a/src/types/external/string.rs b/src/types/external/string.rs index 523ef63d..e2f6d50c 100644 --- a/src/types/external/string.rs +++ b/src/types/external/string.rs @@ -1,13 +1,14 @@ use std::borrow::Cow; -use crate::parser::types::Field; -use crate::registry::Registry; use crate::{ - registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, OutputType, - Positioned, Scalar, ScalarType, ServerResult, Value, + parser::types::Field, registry, registry::Registry, ContextSelectionSet, InputType, + InputValueError, InputValueResult, OutputType, Positioned, Scalar, ScalarType, ServerResult, + Value, }; -/// The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. +/// The `String` scalar type represents textual data, represented as UTF-8 +/// character sequences. The String type is most often used by GraphQL to +/// represent free-form human-readable text. #[Scalar(internal)] impl ScalarType for String { fn parse(value: Value) -> InputValueResult { diff --git a/src/types/external/time_date.rs b/src/types/external/time_date.rs index 099dbe7d..7e3aded4 100644 --- a/src/types/external/time_date.rs +++ b/src/types/external/time_date.rs @@ -1,6 +1,7 @@ -use crate::{InputValueError, InputValueResult, Scalar, ScalarType, Value}; use time::{format_description::FormatItem, macros::format_description, Date}; +use crate::{InputValueError, InputValueResult, Scalar, ScalarType, Value}; + const DATE_FORMAT: &[FormatItem<'_>] = format_description!("[year]-[month]-[day]"); /// ISO 8601 calendar date without timezone. @@ -29,9 +30,10 @@ impl ScalarType for Date { #[cfg(test)] mod tests { - use crate::{ScalarType, Value}; use time::{macros::date, Date}; + use crate::{ScalarType, Value}; + #[test] fn test_date_to_value() { let cases = [ diff --git a/src/types/external/time_offset_date_time.rs b/src/types/external/time_offset_date_time.rs index 8b4a9dbb..c277d47b 100644 --- a/src/types/external/time_offset_date_time.rs +++ b/src/types/external/time_offset_date_time.rs @@ -1,6 +1,7 @@ -use crate::{InputValueError, InputValueResult, Scalar, ScalarType, Value}; use time::{format_description::well_known::Rfc3339, OffsetDateTime, UtcOffset}; +use crate::{InputValueError, InputValueResult, Scalar, ScalarType, Value}; + /// A datetime with timezone offset. /// /// The input is a string in RFC3339 format, e.g. "2022-01-12T04:00:19.12345Z" @@ -31,9 +32,10 @@ impl ScalarType for OffsetDateTime { #[cfg(test)] mod tests { - use crate::{ScalarType, Value}; use time::{macros::datetime, OffsetDateTime}; + use crate::{ScalarType, Value}; + #[test] fn test_offset_date_time_to_value() { let cases = [ diff --git a/src/types/external/time_primitive_date_time.rs b/src/types/external/time_primitive_date_time.rs index 73eade10..75b6de9c 100644 --- a/src/types/external/time_primitive_date_time.rs +++ b/src/types/external/time_primitive_date_time.rs @@ -1,6 +1,7 @@ -use crate::{InputValueError, InputValueResult, Scalar, ScalarType, Value}; use time::{format_description::FormatItem, macros::format_description, PrimitiveDateTime}; +use crate::{InputValueError, InputValueResult, Scalar, ScalarType, Value}; + const PRIMITIVE_DATE_TIME_FORMAT: &[FormatItem<'_>] = format_description!("[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond]"); @@ -27,9 +28,10 @@ impl ScalarType for PrimitiveDateTime { #[cfg(test)] mod tests { - use crate::{ScalarType, Value}; use time::{macros::datetime, PrimitiveDateTime}; + use crate::{ScalarType, Value}; + #[test] fn test_primitive_date_time_to_value() { let cases = [ diff --git a/src/types/external/uuid.rs b/src/types/external/uuid.rs index 135c72bd..f9e7d8de 100644 --- a/src/types/external/uuid.rs +++ b/src/types/external/uuid.rs @@ -7,9 +7,9 @@ use crate::{InputValueError, InputValueResult, Scalar, ScalarType, Value}; name = "UUID", specified_by_url = "http://tools.ietf.org/html/rfc4122" )] -/// A UUID is a unique 128-bit number, stored as 16 octets. UUIDs are parsed as Strings -/// within GraphQL. UUIDs are used to assign unique identifiers to entities without requiring a central -/// allocating authority. +/// A UUID is a unique 128-bit number, stored as 16 octets. UUIDs are parsed as +/// Strings within GraphQL. UUIDs are used to assign unique identifiers to +/// entities without requiring a central allocating authority. /// /// # References /// diff --git a/src/types/id.rs b/src/types/id.rs index 04807019..fad57149 100644 --- a/src/types/id.rs +++ b/src/types/id.rs @@ -1,5 +1,7 @@ -use std::num::ParseIntError; -use std::ops::{Deref, DerefMut}; +use std::{ + num::ParseIntError, + ops::{Deref, DerefMut}, +}; #[cfg(feature = "bson")] use bson::oid::{self, ObjectId}; @@ -9,7 +11,8 @@ use crate::{InputValueError, InputValueResult, Scalar, ScalarType, Value}; /// ID scalar /// -/// The input is a `&str`, `String`, `usize` or `uuid::UUID`, and the output is a string. +/// The input is a `&str`, `String`, `usize` or `uuid::UUID`, and the output is +/// a string. #[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Serialize, Deserialize, Default)] #[serde(transparent)] pub struct ID(pub String); diff --git a/src/types/json.rs b/src/types/json.rs index 89971ccd..af110cfc 100644 --- a/src/types/json.rs +++ b/src/types/json.rs @@ -1,19 +1,22 @@ -use std::borrow::Cow; -use std::ops::{Deref, DerefMut}; +use std::{ + borrow::Cow, + ops::{Deref, DerefMut}, +}; -use serde::de::DeserializeOwned; -use serde::{Deserialize, Serialize}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; -use crate::parser::types::Field; -use crate::registry::{MetaType, MetaTypeId, Registry}; use crate::{ - from_value, to_value, ContextSelectionSet, InputType, InputValueResult, OutputType, Positioned, + from_value, + parser::types::Field, + registry::{MetaType, MetaTypeId, Registry}, + to_value, ContextSelectionSet, InputType, InputValueResult, OutputType, Positioned, ServerResult, Value, }; /// A scalar that can represent any JSON value. /// -/// If the inner type cannot be serialized as JSON (e.g. it has non-string keys) it will be `null`. +/// If the inner type cannot be serialized as JSON (e.g. it has non-string keys) +/// it will be `null`. #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Hash, Default)] #[serde(transparent)] pub struct Json(pub T); @@ -154,10 +157,12 @@ impl OutputType for serde_json::Value { #[cfg(test)] mod test { - use crate::*; - use serde::{Deserialize, Serialize}; use std::collections::HashMap; + use serde::{Deserialize, Serialize}; + + use crate::*; + #[tokio::test] async fn test_json_type() { #[derive(Serialize, Deserialize)] diff --git a/src/types/maybe_undefined.rs b/src/types/maybe_undefined.rs index 6deb7e3c..d1177ded 100644 --- a/src/types/maybe_undefined.rs +++ b/src/types/maybe_undefined.rs @@ -1,5 +1,4 @@ -use std::borrow::Cow; -use std::ops::Deref; +use std::{borrow::Cow, ops::Deref}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; @@ -80,7 +79,8 @@ impl MaybeUndefined { matches!(self, MaybeUndefined::Value(_)) } - /// Borrow the value, returns `None` if the the `MaybeUndefined` is `undefined` or `null`, otherwise returns `Some(T)`. + /// Borrow the value, returns `None` if the the `MaybeUndefined` is + /// `undefined` or `null`, otherwise returns `Some(T)`. #[inline] pub const fn value(&self) -> Option<&T> { match self { @@ -134,7 +134,8 @@ impl MaybeUndefined { } } - /// Returns `true` if the `MaybeUndefined` contains the given nullable value. + /// Returns `true` if the `MaybeUndefined` contains the given nullable + /// value. #[inline] pub fn contains(&self, x: &Option) -> bool where @@ -147,7 +148,8 @@ impl MaybeUndefined { } } - /// Maps a `MaybeUndefined` to `MaybeUndefined` by applying a function to the contained nullable value + /// Maps a `MaybeUndefined` to `MaybeUndefined` by applying a function + /// to the contained nullable value #[inline] pub fn map) -> Option>(self, f: F) -> MaybeUndefined { match self { @@ -163,7 +165,8 @@ impl MaybeUndefined { } } - /// Maps a `MaybeUndefined` to `MaybeUndefined` by applying a function to the contained value + /// Maps a `MaybeUndefined` to `MaybeUndefined` by applying a function + /// to the contained value #[inline] pub fn map_value U>(self, f: F) -> MaybeUndefined { match self { @@ -243,11 +246,14 @@ impl InputType for MaybeUndefined { } impl MaybeUndefined> { - /// Transposes a `MaybeUndefined` of a [`Result`] into a [`Result`] of a `MaybeUndefined`. + /// Transposes a `MaybeUndefined` of a [`Result`] into a [`Result`] of a + /// `MaybeUndefined`. /// - /// [`MaybeUndefined::Undefined`] will be mapped to [`Ok`]`(`[`MaybeUndefined::Undefined`]`)`. - /// [`MaybeUndefined::Null`] will be mapped to [`Ok`]`(`[`MaybeUndefined::Null`]`)`. - /// [`MaybeUndefined::Value`]`(`[`Ok`]`(_))` and [`MaybeUndefined::Value`]`(`[`Err`]`(_))` will be mapped to + /// [`MaybeUndefined::Undefined`] will be mapped to + /// [`Ok`]`(`[`MaybeUndefined::Undefined`]`)`. [`MaybeUndefined::Null`] + /// will be mapped to [`Ok`]`(`[`MaybeUndefined::Null`]`)`. + /// [`MaybeUndefined::Value`]`(`[`Ok`]`(_))` and + /// [`MaybeUndefined::Value`]`(`[`Err`]`(_))` will be mapped to /// [`Ok`]`(`[`MaybeUndefined::Value`]`(_))` and [`Err`]`(_)`. #[inline] pub fn transpose(self) -> Result, E> { @@ -306,9 +312,10 @@ impl From>> for MaybeUndefined { #[cfg(test)] mod tests { - use crate::*; use serde::{Deserialize, Serialize}; + use crate::*; + #[test] fn test_maybe_undefined_type() { assert_eq!(MaybeUndefined::::type_name(), "Int"); diff --git a/src/types/merged_object.rs b/src/types/merged_object.rs index 09fe1b46..214ece9d 100644 --- a/src/types/merged_object.rs +++ b/src/types/merged_object.rs @@ -1,12 +1,11 @@ -use std::borrow::Cow; -use std::pin::Pin; +use std::{borrow::Cow, pin::Pin}; use indexmap::IndexMap; -use crate::futures_util::Stream; -use crate::parser::types::Field; -use crate::registry::{MetaType, MetaTypeId, Registry}; use crate::{ + futures_util::Stream, + parser::types::Field, + registry::{MetaType, MetaTypeId, Registry}, CacheControl, ContainerType, Context, ContextSelectionSet, OutputType, Positioned, Response, ServerResult, SimpleObject, SubscriptionType, Value, }; diff --git a/src/types/mod.rs b/src/types/mod.rs index 4fbddc39..f2fddc68 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -23,8 +23,7 @@ pub use id::ID; pub use json::Json; pub use maybe_undefined::MaybeUndefined; pub use merged_object::{MergedObject, MergedObjectTail}; +pub(crate) use query_root::QueryRoot; #[cfg(feature = "string_number")] pub use string_number::StringNumber; pub use upload::{Upload, UploadValue}; - -pub(crate) use query_root::QueryRoot; diff --git a/src/types/query_root.rs b/src/types/query_root.rs index f8671144..efc83e13 100644 --- a/src/types/query_root.rs +++ b/src/types/query_root.rs @@ -2,14 +2,13 @@ use std::borrow::Cow; use indexmap::map::IndexMap; -use crate::parser::types::Field; -use crate::resolver_utils::{resolve_container, ContainerType}; use crate::{ model::{__Schema, __Type}, + parser::types::Field, + registry, + resolver_utils::{resolve_container, ContainerType}, schema::IntrospectionMode, -}; -use crate::{ - registry, Any, Context, ContextSelectionSet, ObjectType, OutputType, Positioned, ServerError, + Any, Context, ContextSelectionSet, ObjectType, OutputType, Positioned, ServerError, ServerResult, SimpleObject, Value, }; diff --git a/src/types/upload.rs b/src/types/upload.rs index 06b9ed06..2820dcf4 100644 --- a/src/types/upload.rs +++ b/src/types/upload.rs @@ -1,12 +1,11 @@ -use std::borrow::Cow; -use std::fs::File; -use std::io::Read; +use std::{borrow::Cow, fs::File, io::Read}; #[cfg(feature = "unblock")] use futures_util::io::AsyncRead; -use crate::registry::MetaTypeId; -use crate::{registry, Context, InputType, InputValueError, InputValueResult, Value}; +use crate::{ + registry, registry::MetaTypeId, Context, InputType, InputValueError, InputValueResult, Value, +}; /// A file upload value. pub struct UploadValue { @@ -19,8 +18,8 @@ pub struct UploadValue { } impl UploadValue { - /// Attempt to clone the upload value. This type's `Clone` implementation simply calls this and - /// panics on failure. + /// Attempt to clone the upload value. This type's `Clone` implementation + /// simply calls this and panics on failure. /// /// # Errors /// @@ -59,8 +58,8 @@ impl UploadValue { /// /// /// Graphql supports file uploads via `multipart/form-data`. -/// Enable this feature by accepting an argument of type `Upload` (single file) or -/// `Vec` (multiple files) in your mutation like in the example blow. +/// Enable this feature by accepting an argument of type `Upload` (single file) +/// or `Vec` (multiple files) in your mutation like in the example blow. /// /// /// # Example @@ -78,7 +77,6 @@ impl UploadValue { /// true /// } /// } -/// /// ``` /// # Example Curl Request /// diff --git a/src/validation/mod.rs b/src/validation/mod.rs index 53b153e0..3b106f78 100644 --- a/src/validation/mod.rs +++ b/src/validation/mod.rs @@ -8,13 +8,13 @@ mod utils; mod visitor; mod visitors; -use crate::parser::types::ExecutableDocument; -use crate::registry::Registry; -use crate::{CacheControl, ServerError, Variables}; - pub use visitor::VisitorContext; use visitor::{visit, VisitorNil}; +use crate::{ + parser::types::ExecutableDocument, registry::Registry, CacheControl, ServerError, Variables, +}; + /// Validation results. #[derive(Debug, Copy, Clone)] pub struct ValidationResult { @@ -34,7 +34,8 @@ pub enum ValidationMode { /// Execute all validation rules. Strict, - /// The executor itself also has error handling, so it can improve performance, but it can lose some error messages. + /// The executor itself also has error handling, so it can improve + /// performance, but it can lose some error messages. Fast, } diff --git a/src/validation/rules/arguments_of_correct_type.rs b/src/validation/rules/arguments_of_correct_type.rs index c4dc1382..97e2b42b 100644 --- a/src/validation/rules/arguments_of_correct_type.rs +++ b/src/validation/rules/arguments_of_correct_type.rs @@ -1,13 +1,16 @@ +use async_graphql_value::Value; use indexmap::map::IndexMap; -use async_graphql_value::Value; - -use crate::context::QueryPathNode; -use crate::parser::types::{Directive, Field}; -use crate::registry::MetaInputValue; -use crate::validation::utils::is_valid_input_value; -use crate::validation::visitor::{Visitor, VisitorContext}; -use crate::{Name, Positioned, QueryPathSegment}; +use crate::{ + context::QueryPathNode, + parser::types::{Directive, Field}, + registry::MetaInputValue, + validation::{ + utils::is_valid_input_value, + visitor::{Visitor, VisitorContext}, + }, + Name, Positioned, QueryPathSegment, +}; #[derive(Default)] pub struct ArgumentsOfCorrectType<'a> { diff --git a/src/validation/rules/default_values_of_correct_type.rs b/src/validation/rules/default_values_of_correct_type.rs index 35cda594..98d3349d 100644 --- a/src/validation/rules/default_values_of_correct_type.rs +++ b/src/validation/rules/default_values_of_correct_type.rs @@ -1,10 +1,14 @@ use async_graphql_parser::types::BaseType; -use crate::context::QueryPathNode; -use crate::parser::types::VariableDefinition; -use crate::validation::utils::is_valid_input_value; -use crate::validation::visitor::{Visitor, VisitorContext}; -use crate::{Positioned, QueryPathSegment}; +use crate::{ + context::QueryPathNode, + parser::types::VariableDefinition, + validation::{ + utils::is_valid_input_value, + visitor::{Visitor, VisitorContext}, + }, + Positioned, QueryPathSegment, +}; pub struct DefaultValuesOfCorrectType; diff --git a/src/validation/rules/directives_unique.rs b/src/validation/rules/directives_unique.rs index 14e74b18..d04281a8 100644 --- a/src/validation/rules/directives_unique.rs +++ b/src/validation/rules/directives_unique.rs @@ -1,12 +1,14 @@ -use crate::parser::types::{ - Directive, Field, FragmentDefinition, FragmentSpread, InlineFragment, OperationDefinition, - VariableDefinition, -}; -use crate::validation::visitor::Visitor; -use crate::VisitorContext; -use crate::{Name, Positioned}; use std::collections::HashSet; +use crate::{ + parser::types::{ + Directive, Field, FragmentDefinition, FragmentSpread, InlineFragment, OperationDefinition, + VariableDefinition, + }, + validation::visitor::Visitor, + Name, Positioned, VisitorContext, +}; + #[derive(Default)] pub struct DirectivesUnique; diff --git a/src/validation/rules/fields_on_correct_type.rs b/src/validation/rules/fields_on_correct_type.rs index 1b4ad9ef..6fec2e26 100644 --- a/src/validation/rules/fields_on_correct_type.rs +++ b/src/validation/rules/fields_on_correct_type.rs @@ -1,7 +1,12 @@ -use crate::parser::types::Field; -use crate::validation::suggestion::make_suggestion; -use crate::validation::visitor::{Visitor, VisitorContext}; -use crate::{registry, Positioned}; +use crate::{ + parser::types::Field, + registry, + validation::{ + suggestion::make_suggestion, + visitor::{Visitor, VisitorContext}, + }, + Positioned, +}; #[derive(Default)] pub struct FieldsOnCorrectType; diff --git a/src/validation/rules/fragments_on_composite_types.rs b/src/validation/rules/fragments_on_composite_types.rs index f38d9ee9..73100d52 100644 --- a/src/validation/rules/fragments_on_composite_types.rs +++ b/src/validation/rules/fragments_on_composite_types.rs @@ -1,6 +1,8 @@ -use crate::parser::types::{FragmentDefinition, InlineFragment}; -use crate::validation::visitor::{Visitor, VisitorContext}; -use crate::{Name, Positioned}; +use crate::{ + parser::types::{FragmentDefinition, InlineFragment}, + validation::visitor::{Visitor, VisitorContext}, + Name, Positioned, +}; #[derive(Default)] pub struct FragmentsOnCompositeTypes; diff --git a/src/validation/rules/known_argument_names.rs b/src/validation/rules/known_argument_names.rs index 715193a1..81e98de3 100644 --- a/src/validation/rules/known_argument_names.rs +++ b/src/validation/rules/known_argument_names.rs @@ -1,11 +1,15 @@ use async_graphql_value::Value; use indexmap::map::IndexMap; -use crate::parser::types::{Directive, Field}; -use crate::registry::MetaInputValue; -use crate::validation::suggestion::make_suggestion; -use crate::validation::visitor::{Visitor, VisitorContext}; -use crate::{Name, Positioned}; +use crate::{ + parser::types::{Directive, Field}, + registry::MetaInputValue, + validation::{ + suggestion::make_suggestion, + visitor::{Visitor, VisitorContext}, + }, + Name, Positioned, +}; enum ArgsType<'a> { Directive(&'a str), diff --git a/src/validation/rules/known_directives.rs b/src/validation/rules/known_directives.rs index 8f87b22a..7e14572c 100644 --- a/src/validation/rules/known_directives.rs +++ b/src/validation/rules/known_directives.rs @@ -1,10 +1,12 @@ -use crate::model::__DirectiveLocation; -use crate::parser::types::{ - Directive, Field, FragmentDefinition, FragmentSpread, InlineFragment, OperationDefinition, - OperationType, +use crate::{ + model::__DirectiveLocation, + parser::types::{ + Directive, Field, FragmentDefinition, FragmentSpread, InlineFragment, OperationDefinition, + OperationType, + }, + validation::visitor::{Visitor, VisitorContext}, + Name, Positioned, }; -use crate::validation::visitor::{Visitor, VisitorContext}; -use crate::{Name, Positioned}; #[derive(Default)] pub struct KnownDirectives { diff --git a/src/validation/rules/known_fragment_names.rs b/src/validation/rules/known_fragment_names.rs index f034a813..223a5e93 100644 --- a/src/validation/rules/known_fragment_names.rs +++ b/src/validation/rules/known_fragment_names.rs @@ -1,6 +1,8 @@ -use crate::parser::types::FragmentSpread; -use crate::validation::visitor::{Visitor, VisitorContext}; -use crate::Positioned; +use crate::{ + parser::types::FragmentSpread, + validation::visitor::{Visitor, VisitorContext}, + Positioned, +}; #[derive(Default)] pub struct KnownFragmentNames; diff --git a/src/validation/rules/known_type_names.rs b/src/validation/rules/known_type_names.rs index ba13160a..ae6f3677 100644 --- a/src/validation/rules/known_type_names.rs +++ b/src/validation/rules/known_type_names.rs @@ -1,7 +1,9 @@ -use crate::parser::types::{FragmentDefinition, InlineFragment, TypeCondition, VariableDefinition}; -use crate::registry::MetaTypeName; -use crate::validation::visitor::{Visitor, VisitorContext}; -use crate::{Name, Pos, Positioned}; +use crate::{ + parser::types::{FragmentDefinition, InlineFragment, TypeCondition, VariableDefinition}, + registry::MetaTypeName, + validation::visitor::{Visitor, VisitorContext}, + Name, Pos, Positioned, +}; #[derive(Default)] pub struct KnownTypeNames; diff --git a/src/validation/rules/no_fragment_cycles.rs b/src/validation/rules/no_fragment_cycles.rs index 2ae3b9ba..e47c7fb9 100644 --- a/src/validation/rules/no_fragment_cycles.rs +++ b/src/validation/rules/no_fragment_cycles.rs @@ -1,8 +1,10 @@ use std::collections::{HashMap, HashSet}; -use crate::parser::types::{ExecutableDocument, FragmentDefinition, FragmentSpread}; -use crate::validation::visitor::{RuleError, Visitor, VisitorContext}; -use crate::{Name, Pos, Positioned}; +use crate::{ + parser::types::{ExecutableDocument, FragmentDefinition, FragmentSpread}, + validation::visitor::{RuleError, Visitor, VisitorContext}, + Name, Pos, Positioned, +}; struct CycleDetector<'a> { visited: HashSet<&'a str>, diff --git a/src/validation/rules/no_undefined_variables.rs b/src/validation/rules/no_undefined_variables.rs index f84ab7a0..0cfb35d6 100644 --- a/src/validation/rules/no_undefined_variables.rs +++ b/src/validation/rules/no_undefined_variables.rs @@ -1,13 +1,19 @@ use std::collections::{HashMap, HashSet}; -use crate::parser::types::{ - ExecutableDocument, FragmentDefinition, FragmentSpread, OperationDefinition, VariableDefinition, -}; -use crate::validation::utils::{referenced_variables, Scope}; -use crate::validation::visitor::{Visitor, VisitorContext}; -use crate::{Name, Pos, Positioned}; use async_graphql_value::Value; +use crate::{ + parser::types::{ + ExecutableDocument, FragmentDefinition, FragmentSpread, OperationDefinition, + VariableDefinition, + }, + validation::{ + utils::{referenced_variables, Scope}, + visitor::{Visitor, VisitorContext}, + }, + Name, Pos, Positioned, +}; + #[derive(Default)] pub struct NoUndefinedVariables<'a> { defined_variables: HashMap, (Pos, HashSet<&'a str>)>, diff --git a/src/validation/rules/no_unused_fragments.rs b/src/validation/rules/no_unused_fragments.rs index 5e432fd2..a949586d 100644 --- a/src/validation/rules/no_unused_fragments.rs +++ b/src/validation/rules/no_unused_fragments.rs @@ -1,11 +1,13 @@ use std::collections::{HashMap, HashSet}; -use crate::parser::types::{ - ExecutableDocument, FragmentDefinition, FragmentSpread, OperationDefinition, +use crate::{ + parser::types::{ExecutableDocument, FragmentDefinition, FragmentSpread, OperationDefinition}, + validation::{ + utils::Scope, + visitor::{Visitor, VisitorContext}, + }, + Name, Pos, Positioned, }; -use crate::validation::utils::Scope; -use crate::validation::visitor::{Visitor, VisitorContext}; -use crate::{Name, Pos, Positioned}; #[derive(Default)] pub struct NoUnusedFragments<'a> { diff --git a/src/validation/rules/no_unused_variables.rs b/src/validation/rules/no_unused_variables.rs index 44c44f09..81367c21 100644 --- a/src/validation/rules/no_unused_variables.rs +++ b/src/validation/rules/no_unused_variables.rs @@ -2,12 +2,17 @@ use std::collections::{HashMap, HashSet}; use async_graphql_value::Value; -use crate::parser::types::{ - ExecutableDocument, FragmentDefinition, FragmentSpread, OperationDefinition, VariableDefinition, +use crate::{ + parser::types::{ + ExecutableDocument, FragmentDefinition, FragmentSpread, OperationDefinition, + VariableDefinition, + }, + validation::{ + utils::{referenced_variables, Scope}, + visitor::{Visitor, VisitorContext}, + }, + Name, Pos, Positioned, }; -use crate::validation::utils::{referenced_variables, Scope}; -use crate::validation::visitor::{Visitor, VisitorContext}; -use crate::{Name, Pos, Positioned}; #[derive(Default)] pub struct NoUnusedVariables<'a> { diff --git a/src/validation/rules/oneof_fields_have_exactly_one_argument.rs b/src/validation/rules/oneof_fields_have_exactly_one_argument.rs index eaeb69d0..2fcce6fe 100644 --- a/src/validation/rules/oneof_fields_have_exactly_one_argument.rs +++ b/src/validation/rules/oneof_fields_have_exactly_one_argument.rs @@ -1,8 +1,9 @@ -use async_graphql_parser::types::Field; -use async_graphql_parser::Positioned; +use async_graphql_parser::{types::Field, Positioned}; -use crate::validation::visitor::{RuleError, Visitor}; -use crate::{Value, VisitorContext}; +use crate::{ + validation::visitor::{RuleError, Visitor}, + Value, VisitorContext, +}; pub struct OneofFieldsHaveExactlyOneArgument; diff --git a/src/validation/rules/overlapping_fields_can_be_merged.rs b/src/validation/rules/overlapping_fields_can_be_merged.rs index a8032a7e..50ebbf4d 100644 --- a/src/validation/rules/overlapping_fields_can_be_merged.rs +++ b/src/validation/rules/overlapping_fields_can_be_merged.rs @@ -1,8 +1,10 @@ use std::collections::{HashMap, HashSet}; -use crate::parser::types::{Field, Selection, SelectionSet}; -use crate::validation::visitor::{Visitor, VisitorContext}; -use crate::Positioned; +use crate::{ + parser::types::{Field, Selection, SelectionSet}, + validation::visitor::{Visitor, VisitorContext}, + Positioned, +}; #[derive(Default)] pub struct OverlappingFieldsCanBeMerged; @@ -52,7 +54,8 @@ impl<'a, 'ctx> FindConflicts<'a, 'ctx> { .visited .insert(fragment_spread.node.fragment_name.node.as_str()) { - // To avoid recursing itself, this error is detected by the `NoFragmentCycles` validator. + // To avoid recursing itself, this error is detected by the + // `NoFragmentCycles` validator. continue; } self.find(&fragment.node.selection_set); diff --git a/src/validation/rules/possible_fragment_spreads.rs b/src/validation/rules/possible_fragment_spreads.rs index c0e37e97..88809d8a 100644 --- a/src/validation/rules/possible_fragment_spreads.rs +++ b/src/validation/rules/possible_fragment_spreads.rs @@ -1,8 +1,10 @@ use std::collections::HashMap; -use crate::parser::types::{ExecutableDocument, FragmentSpread, InlineFragment, TypeCondition}; -use crate::validation::visitor::{Visitor, VisitorContext}; -use crate::Positioned; +use crate::{ + parser::types::{ExecutableDocument, FragmentSpread, InlineFragment, TypeCondition}, + validation::visitor::{Visitor, VisitorContext}, + Positioned, +}; #[derive(Default)] pub struct PossibleFragmentSpreads<'a> { diff --git a/src/validation/rules/provided_non_null_arguments.rs b/src/validation/rules/provided_non_null_arguments.rs index eed559d6..a38990b6 100644 --- a/src/validation/rules/provided_non_null_arguments.rs +++ b/src/validation/rules/provided_non_null_arguments.rs @@ -1,7 +1,9 @@ -use crate::parser::types::{Directive, Field}; -use crate::registry::MetaTypeName; -use crate::validation::visitor::{Visitor, VisitorContext}; -use crate::Positioned; +use crate::{ + parser::types::{Directive, Field}, + registry::MetaTypeName, + validation::visitor::{Visitor, VisitorContext}, + Positioned, +}; #[derive(Default)] pub struct ProvidedNonNullArguments; diff --git a/src/validation/rules/scalar_leafs.rs b/src/validation/rules/scalar_leafs.rs index b23b9f1e..405d7f32 100644 --- a/src/validation/rules/scalar_leafs.rs +++ b/src/validation/rules/scalar_leafs.rs @@ -1,6 +1,8 @@ -use crate::parser::types::Field; -use crate::validation::visitor::{Visitor, VisitorContext}; -use crate::Positioned; +use crate::{ + parser::types::Field, + validation::visitor::{Visitor, VisitorContext}, + Positioned, +}; #[derive(Default)] pub struct ScalarLeafs; diff --git a/src/validation/rules/unique_argument_names.rs b/src/validation/rules/unique_argument_names.rs index 30f59529..56ca5330 100644 --- a/src/validation/rules/unique_argument_names.rs +++ b/src/validation/rules/unique_argument_names.rs @@ -2,9 +2,11 @@ use std::collections::HashSet; use async_graphql_value::Value; -use crate::parser::types::{Directive, Field}; -use crate::validation::visitor::{Visitor, VisitorContext}; -use crate::{Name, Positioned}; +use crate::{ + parser::types::{Directive, Field}, + validation::visitor::{Visitor, VisitorContext}, + Name, Positioned, +}; #[derive(Default)] pub struct UniqueArgumentNames<'a> { diff --git a/src/validation/rules/unique_variable_names.rs b/src/validation/rules/unique_variable_names.rs index 186672ce..443e3fb2 100644 --- a/src/validation/rules/unique_variable_names.rs +++ b/src/validation/rules/unique_variable_names.rs @@ -1,8 +1,10 @@ use std::collections::HashSet; -use crate::parser::types::{OperationDefinition, VariableDefinition}; -use crate::validation::visitor::{Visitor, VisitorContext}; -use crate::{Name, Positioned}; +use crate::{ + parser::types::{OperationDefinition, VariableDefinition}, + validation::visitor::{Visitor, VisitorContext}, + Name, Positioned, +}; #[derive(Default)] pub struct UniqueVariableNames<'a> { diff --git a/src/validation/rules/upload_file.rs b/src/validation/rules/upload_file.rs index c7fb99ed..e5b656a3 100644 --- a/src/validation/rules/upload_file.rs +++ b/src/validation/rules/upload_file.rs @@ -1,6 +1,8 @@ -use crate::parser::types::{OperationDefinition, OperationType}; -use crate::validation::visitor::{Visitor, VisitorContext}; -use crate::{Name, Positioned}; +use crate::{ + parser::types::{OperationDefinition, OperationType}, + validation::visitor::{Visitor, VisitorContext}, + Name, Positioned, +}; #[derive(Default)] pub struct UploadFile; diff --git a/src/validation/rules/variables_are_input_types.rs b/src/validation/rules/variables_are_input_types.rs index b3a2d067..aca735ea 100644 --- a/src/validation/rules/variables_are_input_types.rs +++ b/src/validation/rules/variables_are_input_types.rs @@ -1,6 +1,8 @@ -use crate::parser::types::VariableDefinition; -use crate::validation::visitor::{Visitor, VisitorContext}; -use crate::Positioned; +use crate::{ + parser::types::VariableDefinition, + validation::visitor::{Visitor, VisitorContext}, + Positioned, +}; #[derive(Default)] pub struct VariablesAreInputTypes; diff --git a/src/validation/rules/variables_in_allowed_position.rs b/src/validation/rules/variables_in_allowed_position.rs index db028f70..4e76e77c 100644 --- a/src/validation/rules/variables_in_allowed_position.rs +++ b/src/validation/rules/variables_in_allowed_position.rs @@ -2,13 +2,18 @@ use std::collections::{HashMap, HashSet}; use async_graphql_value::Value; -use crate::parser::types::{ - ExecutableDocument, FragmentDefinition, FragmentSpread, OperationDefinition, VariableDefinition, +use crate::{ + parser::types::{ + ExecutableDocument, FragmentDefinition, FragmentSpread, OperationDefinition, + VariableDefinition, + }, + registry::MetaTypeName, + validation::{ + utils::Scope, + visitor::{Visitor, VisitorContext}, + }, + Name, Pos, Positioned, }; -use crate::registry::MetaTypeName; -use crate::validation::utils::Scope; -use crate::validation::visitor::{Visitor, VisitorContext}; -use crate::{Name, Pos, Positioned}; #[derive(Default)] pub struct VariableInAllowedPosition<'a> { diff --git a/src/validation/suggestion.rs b/src/validation/suggestion.rs index 6e04566c..c695f56a 100644 --- a/src/validation/suggestion.rs +++ b/src/validation/suggestion.rs @@ -1,5 +1,4 @@ -use std::collections::HashMap; -use std::fmt::Write; +use std::{collections::HashMap, fmt::Write}; fn levenshtein_distance(s1: &str, s2: &str) -> usize { let mut column: Vec<_> = (0..=s1.len()).collect(); diff --git a/src/validation/test_harness.rs b/src/validation/test_harness.rs index fedb2d81..1ef9d543 100644 --- a/src/validation/test_harness.rs +++ b/src/validation/test_harness.rs @@ -4,10 +4,12 @@ use once_cell::sync::Lazy; -use crate::futures_util::Stream; -use crate::parser::types::ExecutableDocument; -use crate::validation::visitor::{visit, RuleError, Visitor, VisitorContext}; -use crate::*; +use crate::{ + futures_util::Stream, + parser::types::ExecutableDocument, + validation::visitor::{visit, RuleError, Visitor, VisitorContext}, + *, +}; #[derive(InputObject)] #[graphql(internal)] diff --git a/src/validation/utils.rs b/src/validation/utils.rs index 59bef875..68453e0f 100644 --- a/src/validation/utils.rs +++ b/src/validation/utils.rs @@ -2,8 +2,7 @@ use std::collections::HashSet; use async_graphql_value::{ConstValue, Value}; -use crate::context::QueryPathNode; -use crate::{registry, QueryPathSegment}; +use crate::{context::QueryPathNode, registry, QueryPathSegment}; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum Scope<'a> { diff --git a/src/validation/visitor.rs b/src/validation/visitor.rs index e202944e..8e8953f7 100644 --- a/src/validation/visitor.rs +++ b/src/validation/visitor.rs @@ -1,14 +1,19 @@ -use std::collections::HashMap; -use std::fmt::{self, Display, Formatter}; +use std::{ + collections::HashMap, + fmt::{self, Display, Formatter}, +}; use async_graphql_value::Value; -use crate::parser::types::{ - Directive, ExecutableDocument, Field, FragmentDefinition, FragmentSpread, InlineFragment, - OperationDefinition, OperationType, Selection, SelectionSet, TypeCondition, VariableDefinition, +use crate::{ + parser::types::{ + Directive, ExecutableDocument, Field, FragmentDefinition, FragmentSpread, InlineFragment, + OperationDefinition, OperationType, Selection, SelectionSet, TypeCondition, + VariableDefinition, + }, + registry::{self, MetaType, MetaTypeName}, + InputType, Name, Pos, Positioned, ServerError, ServerResult, Variables, }; -use crate::registry::{self, MetaType, MetaTypeName}; -use crate::{InputType, Name, Pos, Positioned, ServerError, ServerResult, Variables}; #[doc(hidden)] pub struct VisitorContext<'a> { diff --git a/src/validation/visitors/cache_control.rs b/src/validation/visitors/cache_control.rs index c2cd93e3..9cc06f9e 100644 --- a/src/validation/visitors/cache_control.rs +++ b/src/validation/visitors/cache_control.rs @@ -1,7 +1,9 @@ -use crate::parser::types::{Field, SelectionSet}; -use crate::registry::MetaType; -use crate::validation::visitor::{VisitMode, Visitor, VisitorContext}; -use crate::{CacheControl, Positioned}; +use crate::{ + parser::types::{Field, SelectionSet}, + registry::MetaType, + validation::visitor::{VisitMode, Visitor, VisitorContext}, + CacheControl, Positioned, +}; pub struct CacheControlCalculate<'a> { pub cache_control: &'a mut CacheControl, diff --git a/src/validation/visitors/complexity.rs b/src/validation/visitors/complexity.rs index 2dddcac9..b8fb4406 100644 --- a/src/validation/visitors/complexity.rs +++ b/src/validation/visitors/complexity.rs @@ -1,10 +1,12 @@ use async_graphql_parser::types::{ExecutableDocument, OperationDefinition, VariableDefinition}; use async_graphql_value::Name; -use crate::parser::types::Field; -use crate::registry::{ComplexityType, MetaType, MetaTypeName}; -use crate::validation::visitor::{VisitMode, Visitor, VisitorContext}; -use crate::Positioned; +use crate::{ + parser::types::Field, + registry::{ComplexityType, MetaType, MetaTypeName}, + validation::visitor::{VisitMode, Visitor, VisitorContext}, + Positioned, +}; pub struct ComplexityCalculate<'ctx, 'a> { pub complexity: &'a mut usize, @@ -88,12 +90,15 @@ impl<'ctx, 'a> Visitor<'ctx> for ComplexityCalculate<'ctx, 'a> { #[cfg(test)] mod tests { - use super::*; - use crate::parser::parse_query; - use crate::validation::{visit, VisitorContext}; - use crate::{EmptyMutation, Object, Schema, Subscription}; use futures_util::stream::BoxStream; + use super::*; + use crate::{ + parser::parse_query, + validation::{visit, VisitorContext}, + EmptyMutation, Object, Schema, Subscription, + }; + struct Query; #[derive(Copy, Clone)] diff --git a/src/validation/visitors/depth.rs b/src/validation/visitors/depth.rs index ae536183..21cc9bdb 100644 --- a/src/validation/visitors/depth.rs +++ b/src/validation/visitors/depth.rs @@ -1,7 +1,10 @@ -use crate::validation::visitor::{VisitMode, Visitor, VisitorContext}; -use crate::Positioned; use async_graphql_parser::types::Field; +use crate::{ + validation::visitor::{VisitMode, Visitor, VisitorContext}, + Positioned, +}; + pub struct DepthCalculate<'a> { max_depth: &'a mut usize, current_depth: usize, @@ -34,9 +37,11 @@ impl<'ctx, 'a> Visitor<'ctx> for DepthCalculate<'a> { #[cfg(test)] mod tests { use super::*; - use crate::parser::parse_query; - use crate::validation::{visit, VisitorContext}; - use crate::{EmptyMutation, EmptySubscription, Object, Schema}; + use crate::{ + parser::parse_query, + validation::{visit, VisitorContext}, + EmptyMutation, EmptySubscription, Object, Schema, + }; struct Query; diff --git a/src/validators/email.rs b/src/validators/email.rs index de6e1e60..5d0768c6 100644 --- a/src/validators/email.rs +++ b/src/validators/email.rs @@ -1,6 +1,7 @@ -use crate::{InputType, InputValueError}; use fast_chemail::is_valid_email; +use crate::{InputType, InputValueError}; + pub fn email + InputType>(value: &T) -> Result<(), InputValueError> { if is_valid_email(value.as_ref()) { Ok(()) diff --git a/src/validators/ip.rs b/src/validators/ip.rs index d8744b4b..f553561c 100644 --- a/src/validators/ip.rs +++ b/src/validators/ip.rs @@ -1,5 +1,4 @@ -use std::net::IpAddr; -use std::str::FromStr; +use std::{net::IpAddr, str::FromStr}; use crate::{InputType, InputValueError}; diff --git a/src/validators/min_password_strength.rs b/src/validators/min_password_strength.rs index 510a6dfd..8a96ccec 100644 --- a/src/validators/min_password_strength.rs +++ b/src/validators/min_password_strength.rs @@ -1,6 +1,7 @@ -use crate::{InputType, InputValueError}; use zxcvbn::{zxcvbn, ZxcvbnError}; +use crate::{InputType, InputValueError}; + pub fn min_password_strength + InputType>( value: &T, min_score: u8, diff --git a/src/validators/mod.rs b/src/validators/mod.rs index f5e8537b..17611f73 100644 --- a/src/validators/mod.rs +++ b/src/validators/mod.rs @@ -14,8 +14,6 @@ mod multiple_of; mod regex; mod url; -pub use self::regex::regex; -pub use self::url::url; pub use chars_max_length::chars_max_length; pub use chars_min_length::chars_min_length; pub use email::email; @@ -30,6 +28,7 @@ pub use min_password_strength::min_password_strength; pub use minimum::minimum; pub use multiple_of::multiple_of; +pub use self::{regex::regex, url::url}; use crate::InputType; /// Represents a custom input value validator. diff --git a/src/validators/multiple_of.rs b/src/validators/multiple_of.rs index 72355208..29fd6f96 100644 --- a/src/validators/multiple_of.rs +++ b/src/validators/multiple_of.rs @@ -1,5 +1,4 @@ -use std::fmt::Display; -use std::ops::Rem; +use std::{fmt::Display, ops::Rem}; use num_traits::{AsPrimitive, Zero}; diff --git a/tests/complex_object.rs b/tests/complex_object.rs index 6337979b..0709077e 100644 --- a/tests/complex_object.rs +++ b/tests/complex_object.rs @@ -1,6 +1,7 @@ -use async_graphql::*; use core::marker::PhantomData; +use async_graphql::*; + #[tokio::test] async fn test_complex_object_process_with_method_field() { #[derive(SimpleObject)] diff --git a/tests/connection.rs b/tests/connection.rs index 92b09242..9c96f1cb 100644 --- a/tests/connection.rs +++ b/tests/connection.rs @@ -1,5 +1,4 @@ -use async_graphql::connection::*; -use async_graphql::*; +use async_graphql::{connection::*, *}; #[tokio::test] pub async fn test_connection_additional_fields() { @@ -23,7 +22,9 @@ pub async fn test_connection_additional_fields() { before: Option, first: Option, last: Option, - ) -> Result> { + ) -> Result< + Connection, + > { connection::query( after, before, @@ -43,7 +44,7 @@ pub async fn test_connection_additional_fields() { end < 10000, ConnectionFields { total_count: 10000 }, ); - connection.append((start..end).map(|n| { + connection.edges.extend((start..end).map(|n| { Edge::with_additional_fields( n, n as i32, @@ -63,15 +64,18 @@ pub async fn test_connection_additional_fields() { assert_eq!( schema - .execute("{ numbers(first: 2) { totalCount edges { node diff } } }") + .execute( + "{ numbers(first: 2) { __typename totalCount edges { __typename node diff } } }" + ) .await .data, value!({ "numbers": { + "__typename": "IntConnection", "totalCount": 10000, "edges": [ - {"node": 0, "diff": 10000}, - {"node": 1, "diff": 9999}, + {"__typename": "IntEdge", "node": 0, "diff": 10000}, + {"__typename": "IntEdge", "node": 1, "diff": 9999}, ] }, }) diff --git a/tests/extension.rs b/tests/extension.rs index 15d00147..0cc49861 100644 --- a/tests/extension.rs +++ b/tests/extension.rs @@ -1,16 +1,16 @@ use std::sync::Arc; -use async_graphql::extensions::{ - Extension, ExtensionContext, ExtensionFactory, NextExecute, NextParseQuery, NextPrepareRequest, - NextRequest, NextResolve, NextSubscribe, NextValidation, ResolveInfo, +use async_graphql::{ + extensions::{ + Extension, ExtensionContext, ExtensionFactory, NextExecute, NextParseQuery, + NextPrepareRequest, NextRequest, NextResolve, NextSubscribe, NextValidation, ResolveInfo, + }, + futures_util::stream::BoxStream, + parser::types::ExecutableDocument, + *, }; -use async_graphql::futures_util::stream::BoxStream; -use async_graphql::parser::types::ExecutableDocument; -use async_graphql::*; use async_graphql_value::ConstValue; -use futures_util::lock::Mutex; -use futures_util::stream::Stream; -use futures_util::StreamExt; +use futures_util::{lock::Mutex, stream::Stream, StreamExt}; #[tokio::test] pub async fn test_extension_ctx() { diff --git a/tests/federation.rs b/tests/federation.rs index ef2dc53d..e008957d 100644 --- a/tests/federation.rs +++ b/tests/federation.rs @@ -1,10 +1,11 @@ #![allow(unreachable_code)] -use std::collections::HashMap; -use std::convert::Infallible; +use std::{collections::HashMap, convert::Infallible}; -use async_graphql::dataloader::{DataLoader, Loader}; -use async_graphql::*; +use async_graphql::{ + dataloader::{DataLoader, Loader}, + *, +}; #[tokio::test] pub async fn test_nested_key() { diff --git a/tests/guard.rs b/tests/guard.rs index a7963f26..32227608 100644 --- a/tests/guard.rs +++ b/tests/guard.rs @@ -1,5 +1,4 @@ -use async_graphql::Guard; -use async_graphql::*; +use async_graphql::{Guard, *}; use futures_util::stream::{Stream, StreamExt}; #[derive(Eq, PartialEq, Copy, Clone)] diff --git a/tests/hygiene.rs b/tests/hygiene.rs index 13378773..4bfb70c1 100644 --- a/tests/hygiene.rs +++ b/tests/hygiene.rs @@ -2,13 +2,12 @@ #![no_implicit_prelude] // TODO: remove this: https://github.com/dtolnay/async-trait/issues/132 +use ::async_graphql::{self, InputValueResult, ScalarType, Value}; +use ::serde::{Deserialize, Serialize}; use ::std::boxed::Box; // TODO: remove this: https://github.com/nvzqz/static-assertions-rs/issues/37 use ::std::marker::Sized; -use ::async_graphql::{self, InputValueResult, ScalarType, Value}; -use ::serde::{Deserialize, Serialize}; - struct MyObject; #[async_graphql::Object] impl MyObject { diff --git a/tests/input_object.rs b/tests/input_object.rs index acc3eb44..345a3fec 100644 --- a/tests/input_object.rs +++ b/tests/input_object.rs @@ -561,7 +561,7 @@ pub async fn test_input_object_process_with() { } #[derive(InputObject)] struct MyInput { - //processor does nothing on default value + // processor does nothing on default value #[graphql(default = " ", process_with = "processor::string")] a: String, diff --git a/tests/input_value.rs b/tests/input_value.rs index 6fbd1a29..79b1dec1 100644 --- a/tests/input_value.rs +++ b/tests/input_value.rs @@ -1,6 +1,7 @@ -use async_graphql::*; use std::sync::Arc; +use async_graphql::*; + #[tokio::test] pub async fn test_input_value_custom_error() { struct Query; diff --git a/tests/json_type.rs b/tests/json_type.rs index b69425ea..90654148 100644 --- a/tests/json_type.rs +++ b/tests/json_type.rs @@ -1,6 +1,7 @@ -use async_graphql::*; use std::collections::HashMap; +use async_graphql::*; + #[tokio::test] pub async fn test_json_scalar() { #[derive(serde::Serialize, serde::Deserialize)] diff --git a/tests/list.rs b/tests/list.rs index 8084b6ff..8ea2adb9 100644 --- a/tests/list.rs +++ b/tests/list.rs @@ -1,6 +1,9 @@ +use std::{ + cmp::Ordering, + collections::{BTreeSet, HashSet, LinkedList, VecDeque}, +}; + use async_graphql::*; -use std::cmp::Ordering; -use std::collections::{BTreeSet, HashSet, LinkedList, VecDeque}; #[tokio::test] pub async fn test_list_type() { diff --git a/tests/mutation.rs b/tests/mutation.rs index 853d0347..406f4043 100644 --- a/tests/mutation.rs +++ b/tests/mutation.rs @@ -1,6 +1,6 @@ +use std::{sync::Arc, time::Duration}; + use async_graphql::*; -use std::sync::Arc; -use std::time::Duration; use tokio::sync::Mutex; #[tokio::test] diff --git a/tests/oneof_object.rs b/tests/oneof_object.rs index 8a36db0e..199d769f 100644 --- a/tests/oneof_object.rs +++ b/tests/oneof_object.rs @@ -1,5 +1,7 @@ -use async_graphql::registry::{MetaType, Registry}; -use async_graphql::*; +use async_graphql::{ + registry::{MetaType, Registry}, + *, +}; #[tokio::test] async fn test_oneof_object() { diff --git a/tests/simple_object.rs b/tests/simple_object.rs index 540f44de..293d293b 100644 --- a/tests/simple_object.rs +++ b/tests/simple_object.rs @@ -64,7 +64,8 @@ async fn recursive_fragment_definition() { struct Query; - // this setup is actually completely irrelevant we just need to be able ot execute a query + // this setup is actually completely irrelevant we just need to be able ot + // execute a query #[Object] impl Query { async fn obj(&self) -> Hello { @@ -88,7 +89,8 @@ async fn recursive_fragment_definition_nested() { struct Query; - // this setup is actually completely irrelevant we just need to be able ot execute a query + // this setup is actually completely irrelevant we just need to be able ot + // execute a query #[Object] impl Query { async fn obj(&self) -> Hello { diff --git a/tests/subscription_websocket_graphql_ws.rs b/tests/subscription_websocket_graphql_ws.rs index 503e9bd2..3307b29b 100644 --- a/tests/subscription_websocket_graphql_ws.rs +++ b/tests/subscription_websocket_graphql_ws.rs @@ -1,12 +1,15 @@ -use std::pin::Pin; -use std::sync::{Arc, Mutex}; -use std::time::Duration; +use std::{ + pin::Pin, + sync::{Arc, Mutex}, + time::Duration, +}; -use async_graphql::http::WebSocketProtocols; -use async_graphql::*; +use async_graphql::{http::WebSocketProtocols, *}; use futures_channel::mpsc; -use futures_util::stream::{BoxStream, Stream, StreamExt}; -use futures_util::SinkExt; +use futures_util::{ + stream::{BoxStream, Stream, StreamExt}, + SinkExt, +}; #[tokio::test] pub async fn test_subscription_ws_transport() { diff --git a/tests/subscription_websocket_subscriptions_transport_ws.rs b/tests/subscription_websocket_subscriptions_transport_ws.rs index fb170a3c..b6beb4b0 100644 --- a/tests/subscription_websocket_subscriptions_transport_ws.rs +++ b/tests/subscription_websocket_subscriptions_transport_ws.rs @@ -1,8 +1,9 @@ -use async_graphql::http::WebSocketProtocols; -use async_graphql::*; +use async_graphql::{http::WebSocketProtocols, *}; use futures_channel::mpsc; -use futures_util::stream::{Stream, StreamExt}; -use futures_util::SinkExt; +use futures_util::{ + stream::{Stream, StreamExt}, + SinkExt, +}; #[tokio::test] pub async fn test_subscription_ws_transport() { diff --git a/tests/validators.rs b/tests/validators.rs index 9bc2317a..54940b97 100644 --- a/tests/validators.rs +++ b/tests/validators.rs @@ -1,6 +1,7 @@ +use std::sync::Arc; + use async_graphql::*; use futures_util::{Stream, StreamExt}; -use std::sync::Arc; #[tokio::test] pub async fn test_all_validator() { diff --git a/tests/variables.rs b/tests/variables.rs index 70b0f8bb..2d4b1059 100644 --- a/tests/variables.rs +++ b/tests/variables.rs @@ -1,6 +1,7 @@ -use async_graphql::*; use std::collections::HashMap; +use async_graphql::*; + #[tokio::test] pub async fn test_variables() { struct Query; diff --git a/value/src/deserializer.rs b/value/src/deserializer.rs index 36ba0dbf..eb14d7b6 100644 --- a/value/src/deserializer.rs +++ b/value/src/deserializer.rs @@ -1,15 +1,16 @@ use std::{fmt, vec}; use indexmap::IndexMap; +use serde::{ + de::{ + self, Deserialize, DeserializeOwned, DeserializeSeed, EnumAccess, Error as DeError, + IntoDeserializer, MapAccess, SeqAccess, Unexpected, VariantAccess, Visitor, + }, + forward_to_deserialize_any, +}; use crate::{ConstValue, Name}; -use serde::de::{ - self, Deserialize, DeserializeOwned, DeserializeSeed, EnumAccess, Error as DeError, - IntoDeserializer, MapAccess, SeqAccess, Unexpected, VariantAccess, Visitor, -}; -use serde::forward_to_deserialize_any; - /// This type represents errors that can occur when deserializing. #[derive(Debug)] pub struct DeserializerError(String); diff --git a/value/src/lib.rs b/value/src/lib.rs index bf40e624..e25d1433 100644 --- a/value/src/lib.rs +++ b/value/src/lib.rs @@ -9,21 +9,21 @@ mod serializer; mod value_serde; mod variables; -use std::borrow::{Borrow, Cow}; -use std::fmt::{self, Display, Formatter, Write}; -use std::ops::Deref; -use std::sync::Arc; +use std::{ + borrow::{Borrow, Cow}, + fmt::{self, Display, Formatter, Write}, + ops::Deref, + sync::Arc, +}; use bytes::Bytes; -use indexmap::IndexMap; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; - pub use deserializer::{from_value, DeserializerError}; #[doc(hidden)] pub use indexmap; +use indexmap::IndexMap; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; pub use serde_json::Number; pub use serializer::{to_value, SerializerError}; - pub use variables::Variables; /// A GraphQL name. @@ -118,8 +118,9 @@ impl<'de> Deserialize<'de> for Name { /// A resolved GraphQL value, for example `1` or `"Hello World!"`. /// -/// It can be serialized and deserialized. Enums will be converted to strings. Attempting to -/// serialize `Upload` will fail, and `Enum` and `Upload` cannot be deserialized. +/// It can be serialized and deserialized. Enums will be converted to strings. +/// Attempting to serialize `Upload` will fail, and `Enum` and `Upload` cannot +/// be deserialized. /// /// [Reference](https://spec.graphql.org/June2018/#Value). #[derive(Clone, Debug, Eq)] @@ -282,7 +283,8 @@ impl ConstValue { } } - /// Attempt to convert the value into JSON. This is equivalent to the `TryFrom` implementation. + /// Attempt to convert the value into JSON. This is equivalent to the + /// `TryFrom` implementation. /// /// # Errors /// @@ -291,7 +293,8 @@ impl ConstValue { self.try_into() } - /// Attempt to convert JSON into a value. This is equivalent to the `TryFrom` implementation. + /// Attempt to convert JSON into a value. This is equivalent to the + /// `TryFrom` implementation. /// /// # Errors /// @@ -340,9 +343,9 @@ impl TryFrom for serde_json::Value { /// A GraphQL value, for example `1`, `$name` or `"Hello World!"`. This is /// [`ConstValue`](enum.ConstValue.html) with variables. /// -/// It can be serialized and deserialized. Enums will be converted to strings. Attempting to -/// serialize `Upload` or `Variable` will fail, and `Enum`, `Upload` and `Variable` cannot be -/// deserialized. +/// It can be serialized and deserialized. Enums will be converted to strings. +/// Attempting to serialize `Upload` or `Variable` will fail, and `Enum`, +/// `Upload` and `Variable` cannot be deserialized. /// /// [Reference](https://spec.graphql.org/June2018/#Value). #[derive(Clone, Debug, PartialEq, Eq)] @@ -368,7 +371,8 @@ pub enum Value { } impl Value { - /// Attempt to convert the value into a const value by using a function to get a variable. + /// Attempt to convert the value into a const value by using a function to + /// get a variable. pub fn into_const_with( self, mut f: impl FnMut(Name) -> Result, @@ -410,7 +414,8 @@ impl Value { self.into_const_with(|_| Err(())).ok() } - /// Attempt to convert the value into JSON. This is equivalent to the `TryFrom` implementation. + /// Attempt to convert the value into JSON. This is equivalent to the + /// `TryFrom` implementation. /// /// # Errors /// @@ -419,7 +424,8 @@ impl Value { self.try_into() } - /// Attempt to convert JSON into a value. This is equivalent to the `TryFrom` implementation. + /// Attempt to convert JSON into a value. This is equivalent to the + /// `TryFrom` implementation. /// /// # Errors /// diff --git a/value/src/macros.rs b/value/src/macros.rs index 4be7cc12..263b9983 100644 --- a/value/src/macros.rs +++ b/value/src/macros.rs @@ -226,9 +226,10 @@ macro_rules! value_expect_expr_comma { #[cfg(test)] mod tests { - use crate::{ConstValue, Name}; use indexmap::IndexMap; + use crate::{ConstValue, Name}; + #[test] fn test_macro() { assert_eq!(value!(1), ConstValue::Number(1.into())); diff --git a/value/src/serializer.rs b/value/src/serializer.rs index ac198822..0fd769c9 100644 --- a/value/src/serializer.rs +++ b/value/src/serializer.rs @@ -1,9 +1,10 @@ -use std::error::Error; -use std::fmt; +use std::{error::Error, fmt}; use indexmap::IndexMap; -use serde::ser::{self, Impossible}; -use serde::Serialize; +use serde::{ + ser::{self, Impossible}, + Serialize, +}; use crate::{ConstValue, Name, Number}; @@ -31,7 +32,8 @@ impl ser::Error for SerializerError { } } -/// Convert a `T` into `ConstValue` which is an enum that can represent any valid GraphQL data. +/// Convert a `T` into `ConstValue` which is an enum that can represent any +/// valid GraphQL data. #[inline] pub fn to_value(value: T) -> Result { value.serialize(Serializer) diff --git a/value/src/value_serde.rs b/value/src/value_serde.rs index 3d6aa76a..806f3624 100644 --- a/value/src/value_serde.rs +++ b/value/src/value_serde.rs @@ -1,9 +1,11 @@ use std::fmt::{self, Formatter}; use indexmap::IndexMap; -use serde::de::{Error as DeError, MapAccess, SeqAccess, Visitor}; -use serde::ser::Error as SerError; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use serde::{ + de::{Error as DeError, MapAccess, SeqAccess, Visitor}, + ser::Error as SerError, + Deserialize, Deserializer, Serialize, Serializer, +}; use crate::{ConstValue, Number, Value}; diff --git a/value/src/variables.rs b/value/src/variables.rs index 8599085c..9b3acd29 100644 --- a/value/src/variables.rs +++ b/value/src/variables.rs @@ -1,6 +1,8 @@ -use std::collections::BTreeMap; -use std::fmt::{self, Display, Formatter}; -use std::ops::{Deref, DerefMut}; +use std::{ + collections::BTreeMap, + fmt::{self, Display, Formatter}, + ops::{Deref, DerefMut}, +}; use serde::{Deserialize, Deserializer, Serialize}; @@ -43,8 +45,8 @@ impl Variables { /// Get the values from a JSON value. /// - /// If the value is not a map or the keys of a map are not valid GraphQL names, then no - /// variables will be returned. + /// If the value is not a map or the keys of a map are not valid GraphQL + /// names, then no variables will be returned. #[must_use] pub fn from_json(value: serde_json::Value) -> Self { ConstValue::from_json(value) diff --git a/value/tests/test_serde.rs b/value/tests/test_serde.rs index 2877d5a5..7c58ff61 100644 --- a/value/tests/test_serde.rs +++ b/value/tests/test_serde.rs @@ -1,9 +1,8 @@ +use std::{collections::BTreeMap, fmt::Debug}; + use async_graphql_value::*; use bytes::Bytes; -use serde::de::DeserializeOwned; -use serde::{Deserialize, Serialize}; -use std::collections::BTreeMap; -use std::fmt::Debug; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; fn test_value(value: T) { assert_eq!(