Move the methods of the `Type` trait to `InputType` and `OutputType`.
This commit is contained in:
parent
b85815d84a
commit
0e9e087691
|
@ -115,7 +115,7 @@ impl FromMeta for Deprecation {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(FromField, Clone)]
|
||||
#[derive(FromField)]
|
||||
#[darling(attributes(graphql), forward_attrs(doc))]
|
||||
pub struct SimpleObjectField {
|
||||
pub ident: Option<Ident>,
|
||||
|
@ -145,6 +145,17 @@ pub struct SimpleObjectField {
|
|||
pub visible: Option<Visible>,
|
||||
#[darling(default, multiple)]
|
||||
pub derived: Vec<DerivedField>,
|
||||
// for InputObject
|
||||
#[darling(default)]
|
||||
pub default: Option<DefaultValue>,
|
||||
#[darling(default)]
|
||||
pub default_with: Option<LitStr>,
|
||||
#[darling(default)]
|
||||
pub validator: Option<Meta>,
|
||||
#[darling(default)]
|
||||
pub flatten: bool,
|
||||
#[darling(default)]
|
||||
pub secret: bool,
|
||||
}
|
||||
|
||||
#[derive(FromDeriveInput)]
|
||||
|
@ -158,7 +169,7 @@ pub struct SimpleObject {
|
|||
#[darling(default)]
|
||||
pub internal: bool,
|
||||
#[darling(default)]
|
||||
pub dummy: bool,
|
||||
pub fake: bool,
|
||||
#[darling(default)]
|
||||
pub complex: bool,
|
||||
#[darling(default)]
|
||||
|
@ -177,6 +188,9 @@ pub struct SimpleObject {
|
|||
pub concretes: Vec<ConcreteType>,
|
||||
#[darling(default)]
|
||||
pub serial: bool,
|
||||
// for InputObject
|
||||
#[darling(default)]
|
||||
pub input_name: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(FromMeta, Default)]
|
||||
|
@ -362,6 +376,8 @@ pub struct InputObject {
|
|||
#[darling(default)]
|
||||
pub name: Option<String>,
|
||||
#[darling(default)]
|
||||
pub input_name: Option<String>,
|
||||
#[darling(default)]
|
||||
pub rename_fields: Option<RenameRule>,
|
||||
#[darling(default)]
|
||||
pub visible: Option<Visible>,
|
||||
|
|
|
@ -218,7 +218,7 @@ pub fn generate(
|
|||
args.insert(#name, #crate_name::registry::MetaInputValue {
|
||||
name: #name,
|
||||
description: #desc,
|
||||
ty: <#ty as #crate_name::Type>::create_type_info(registry),
|
||||
ty: <#ty as #crate_name::InputType>::create_type_info(registry),
|
||||
default_value: #schema_default,
|
||||
validator: #validator,
|
||||
visible: #visible,
|
||||
|
@ -310,7 +310,7 @@ pub fn generate(
|
|||
#(#schema_args)*
|
||||
args
|
||||
},
|
||||
ty: <#schema_ty as #crate_name::Type>::create_type_info(registry),
|
||||
ty: <#schema_ty as #crate_name::OutputType>::create_type_info(registry),
|
||||
deprecation: #field_deprecation,
|
||||
cache_control: #cache_control,
|
||||
external: #external,
|
||||
|
|
|
@ -124,13 +124,13 @@ pub fn generate(enum_args: &args::Enum) -> GeneratorResult<TokenStream> {
|
|||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::Type for #ident {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
impl #ident {
|
||||
fn __type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
registry.create_type::<Self, _>(|registry| {
|
||||
fn __create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
registry.create_input_type::<Self, _>(|registry| {
|
||||
#crate_name::registry::MetaType::Enum {
|
||||
name: ::std::borrow::ToOwned::to_owned(#gql_typename),
|
||||
description: #desc,
|
||||
|
@ -148,6 +148,14 @@ pub fn generate(enum_args: &args::Enum) -> GeneratorResult<TokenStream> {
|
|||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::InputType for #ident {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
Self::__type_name()
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
Self::__create_type_info(registry)
|
||||
}
|
||||
|
||||
fn parse(value: ::std::option::Option<#crate_name::Value>) -> #crate_name::InputValueResult<Self> {
|
||||
#crate_name::resolver_utils::parse_enum(value.unwrap_or_default())
|
||||
}
|
||||
|
@ -159,6 +167,14 @@ pub fn generate(enum_args: &args::Enum) -> GeneratorResult<TokenStream> {
|
|||
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #crate_name::OutputType for #ident {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
Self::__type_name()
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
Self::__create_type_info(registry)
|
||||
}
|
||||
|
||||
async fn resolve(&self, _: &#crate_name::ContextSelectionSet<'_>, _field: &#crate_name::Positioned<#crate_name::parser::types::Field>) -> #crate_name::ServerResult<#crate_name::Value> {
|
||||
::std::result::Result::Ok(#crate_name::resolver_utils::enum_value(*self))
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ pub fn generate(object_args: &args::InputObject) -> GeneratorResult<TokenStream>
|
|||
let gql_typename = object_args
|
||||
.name
|
||||
.clone()
|
||||
.or_else(|| object_args.input_name.clone())
|
||||
.unwrap_or_else(|| RenameTarget::Type.rename(ident.to_string()));
|
||||
|
||||
let desc = get_rustdoc(&object_args.attrs)?
|
||||
|
@ -83,7 +84,7 @@ pub fn generate(object_args: &args::InputObject) -> GeneratorResult<TokenStream>
|
|||
#crate_name::static_assertions::assert_impl_one!(#ty: #crate_name::InputObjectType);
|
||||
#ty::create_type_info(registry);
|
||||
if let #crate_name::registry::MetaType::InputObject { input_fields, .. } =
|
||||
registry.create_dummy_type::<#ty>() {
|
||||
registry.create_fake_input_type::<#ty>() {
|
||||
fields.extend(input_fields);
|
||||
}
|
||||
});
|
||||
|
@ -161,7 +162,7 @@ pub fn generate(object_args: &args::InputObject) -> GeneratorResult<TokenStream>
|
|||
fields.insert(::std::borrow::ToOwned::to_owned(#name), #crate_name::registry::MetaInputValue {
|
||||
name: #name,
|
||||
description: #desc,
|
||||
ty: <#ty as #crate_name::Type>::create_type_info(registry),
|
||||
ty: <#ty as #crate_name::InputType>::create_type_info(registry),
|
||||
default_value: #schema_default,
|
||||
validator: #validator,
|
||||
visible: #visible,
|
||||
|
@ -200,13 +201,13 @@ pub fn generate(object_args: &args::InputObject) -> GeneratorResult<TokenStream>
|
|||
let expanded = if object_args.concretes.is_empty() {
|
||||
quote! {
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::Type for #ident {
|
||||
impl #crate_name::InputType for #ident {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
registry.create_type::<Self, _>(|registry| #crate_name::registry::MetaType::InputObject {
|
||||
registry.create_input_type::<Self, _>(|registry| #crate_name::registry::MetaType::InputObject {
|
||||
name: ::std::borrow::ToOwned::to_owned(#gql_typename),
|
||||
description: #desc,
|
||||
input_fields: {
|
||||
|
@ -218,10 +219,7 @@ pub fn generate(object_args: &args::InputObject) -> GeneratorResult<TokenStream>
|
|||
rust_typename: ::std::any::type_name::<Self>(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::InputType for #ident {
|
||||
fn parse(value: ::std::option::Option<#crate_name::Value>) -> #crate_name::InputValueResult<Self> {
|
||||
if let ::std::option::Option::Some(#crate_name::Value::Object(obj)) = value {
|
||||
#(#get_fields)*
|
||||
|
@ -251,7 +249,7 @@ pub fn generate(object_args: &args::InputObject) -> GeneratorResult<TokenStream>
|
|||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #impl_generics #ident #ty_generics #where_clause {
|
||||
fn __internal_create_type_info(registry: &mut #crate_name::registry::Registry, name: &str) -> ::std::string::String where Self: #crate_name::InputType {
|
||||
registry.create_type::<Self, _>(|registry| #crate_name::registry::MetaType::InputObject {
|
||||
registry.create_input_type::<Self, _>(|registry| #crate_name::registry::MetaType::InputObject {
|
||||
name: ::std::borrow::ToOwned::to_owned(name),
|
||||
description: #desc,
|
||||
input_fields: {
|
||||
|
@ -292,7 +290,7 @@ pub fn generate(object_args: &args::InputObject) -> GeneratorResult<TokenStream>
|
|||
|
||||
let expanded = quote! {
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::Type for #concrete_type {
|
||||
impl #crate_name::InputType for #concrete_type {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
@ -300,10 +298,7 @@ pub fn generate(object_args: &args::InputObject) -> GeneratorResult<TokenStream>
|
|||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
Self::__internal_create_type_info(registry, #gql_typename)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::InputType for #concrete_type {
|
||||
fn parse(value: ::std::option::Option<#crate_name::Value>) -> #crate_name::InputValueResult<Self> {
|
||||
Self::__internal_parse(value)
|
||||
}
|
||||
|
|
|
@ -100,16 +100,16 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult<TokenStream
|
|||
enum_names.push(enum_name);
|
||||
|
||||
registry_types.push(quote! {
|
||||
<#p as #crate_name::Type>::create_type_info(registry);
|
||||
registry.add_implements(&<#p as #crate_name::Type>::type_name(), #gql_typename);
|
||||
<#p as #crate_name::OutputType>::create_type_info(registry);
|
||||
registry.add_implements(&<#p as #crate_name::OutputType>::type_name(), #gql_typename);
|
||||
});
|
||||
|
||||
possible_types.push(quote! {
|
||||
possible_types.insert(<#p as #crate_name::Type>::type_name().into_owned());
|
||||
possible_types.insert(<#p as #crate_name::OutputType>::type_name().into_owned());
|
||||
});
|
||||
|
||||
get_introspection_typename.push(quote! {
|
||||
#ident::#enum_name(obj) => <#p as #crate_name::Type>::type_name()
|
||||
#ident::#enum_name(obj) => <#p as #crate_name::OutputType>::type_name()
|
||||
});
|
||||
|
||||
collect_all_fields.push(quote! {
|
||||
|
@ -226,7 +226,7 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult<TokenStream
|
|||
args.insert(#name, #crate_name::registry::MetaInputValue {
|
||||
name: #name,
|
||||
description: #desc,
|
||||
ty: <#ty as #crate_name::Type>::create_type_info(registry),
|
||||
ty: <#ty as #crate_name::InputType>::create_type_info(registry),
|
||||
default_value: #schema_default,
|
||||
validator: ::std::option::Option::None,
|
||||
visible: #visible,
|
||||
|
@ -275,7 +275,7 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult<TokenStream
|
|||
#(#schema_args)*
|
||||
args
|
||||
},
|
||||
ty: <#schema_ty as #crate_name::Type>::create_type_info(registry),
|
||||
ty: <#schema_ty as #crate_name::OutputType>::create_type_info(registry),
|
||||
deprecation: #deprecation,
|
||||
cache_control: ::std::default::Default::default(),
|
||||
external: #external,
|
||||
|
@ -321,7 +321,23 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult<TokenStream
|
|||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #impl_generics #crate_name::Type for #ident #ty_generics #where_clause {
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #impl_generics #crate_name::resolver_utils::ContainerType for #ident #ty_generics #where_clause {
|
||||
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::ServerResult<::std::option::Option<#crate_name::Value>> {
|
||||
#(#resolvers)*
|
||||
::std::result::Result::Ok(::std::option::Option::None)
|
||||
}
|
||||
|
||||
fn collect_all_fields<'__life>(&'__life self, ctx: &#crate_name::ContextSelectionSet<'__life>, fields: &mut #crate_name::resolver_utils::Fields<'__life>) -> #crate_name::ServerResult<()> {
|
||||
match self {
|
||||
#(#collect_all_fields),*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #impl_generics #crate_name::OutputType for #ident #ty_generics #where_clause {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
@ -331,7 +347,7 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult<TokenStream
|
|||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
registry.create_type::<Self, _>(|registry| {
|
||||
registry.create_output_type::<Self, _>(|registry| {
|
||||
#(#registry_types)*
|
||||
|
||||
#crate_name::registry::MetaType::Interface {
|
||||
|
@ -354,26 +370,7 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult<TokenStream
|
|||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #impl_generics #crate_name::resolver_utils::ContainerType for #ident #ty_generics #where_clause {
|
||||
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::ServerResult<::std::option::Option<#crate_name::Value>> {
|
||||
#(#resolvers)*
|
||||
::std::result::Result::Ok(::std::option::Option::None)
|
||||
}
|
||||
|
||||
fn collect_all_fields<'__life>(&'__life self, ctx: &#crate_name::ContextSelectionSet<'__life>, fields: &mut #crate_name::resolver_utils::Fields<'__life>) -> #crate_name::ServerResult<()> {
|
||||
match self {
|
||||
#(#collect_all_fields),*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #impl_generics #crate_name::OutputType for #ident #ty_generics #where_clause {
|
||||
async fn resolve(
|
||||
&self,
|
||||
ctx: &#crate_name::ContextSelectionSet<'_>,
|
||||
|
|
|
@ -63,13 +63,26 @@ pub fn generate(object_args: &args::MergedObject) -> GeneratorResult<TokenStream
|
|||
|
||||
let expanded = quote! {
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #impl_generics #crate_name::Type for #ident #ty_generics #where_clause {
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #impl_generics #crate_name::resolver_utils::ContainerType for #ident #ty_generics #where_clause {
|
||||
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::ServerResult<::std::option::Option<#crate_name::Value>> {
|
||||
#create_merged_obj.resolve_field(ctx).await
|
||||
}
|
||||
|
||||
async fn find_entity(&self, ctx: &#crate_name::Context<'_>, params: &#crate_name::Value) -> #crate_name::ServerResult<::std::option::Option<#crate_name::Value>> {
|
||||
#create_merged_obj.find_entity(ctx, params).await
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #impl_generics #crate_name::OutputType for #ident #ty_generics #where_clause {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
registry.create_type::<Self, _>(|registry| {
|
||||
registry.create_output_type::<Self, _>(|registry| {
|
||||
let mut fields = ::std::default::Default::default();
|
||||
let mut cache_control = ::std::default::Default::default();
|
||||
|
||||
|
@ -77,7 +90,7 @@ pub fn generate(object_args: &args::MergedObject) -> GeneratorResult<TokenStream
|
|||
fields: obj_fields,
|
||||
cache_control: obj_cache_control,
|
||||
..
|
||||
} = registry.create_dummy_type::<#merged_type>() {
|
||||
} = registry.create_fake_output_type::<#merged_type>() {
|
||||
fields = obj_fields;
|
||||
cache_control = obj_cache_control;
|
||||
}
|
||||
|
@ -95,23 +108,7 @@ pub fn generate(object_args: &args::MergedObject) -> GeneratorResult<TokenStream
|
|||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #impl_generics #crate_name::resolver_utils::ContainerType for #ident #ty_generics #where_clause {
|
||||
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::ServerResult<::std::option::Option<#crate_name::Value>> {
|
||||
#create_merged_obj.resolve_field(ctx).await
|
||||
}
|
||||
|
||||
async fn find_entity(&self, ctx: &#crate_name::Context<'_>, params: &#crate_name::Value) -> #crate_name::ServerResult<::std::option::Option<#crate_name::Value>> {
|
||||
#create_merged_obj.find_entity(ctx, params).await
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #impl_generics #crate_name::OutputType for #ident #ty_generics #where_clause {
|
||||
async fn resolve(&self, ctx: &#crate_name::ContextSelectionSet<'_>, _field: &#crate_name::Positioned<#crate_name::parser::types::Field>) -> #crate_name::ServerResult<#crate_name::Value> {
|
||||
#resolve_container
|
||||
}
|
||||
|
|
|
@ -48,19 +48,19 @@ pub fn generate(object_args: &args::MergedSubscription) -> GeneratorResult<Token
|
|||
let visible = visible_fn(&object_args.visible);
|
||||
let expanded = quote! {
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::Type for #ident {
|
||||
impl #crate_name::SubscriptionType for #ident {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
registry.create_type::<Self, _>(|registry| {
|
||||
registry.create_subscription_type::<Self, _>(|registry| {
|
||||
let mut fields = ::std::default::Default::default();
|
||||
|
||||
if let #crate_name::registry::MetaType::Object {
|
||||
fields: obj_fields,
|
||||
..
|
||||
} = registry.create_dummy_type::<#merged_type>() {
|
||||
} = registry.create_fake_subscription_type::<#merged_type>() {
|
||||
fields = obj_fields;
|
||||
}
|
||||
|
||||
|
@ -77,10 +77,7 @@ pub fn generate(object_args: &args::MergedSubscription) -> GeneratorResult<Token
|
|||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::SubscriptionType for #ident {
|
||||
fn create_field_stream<'__life>(
|
||||
&'__life self,
|
||||
ctx: &'__life #crate_name::Context<'__life>
|
||||
|
|
|
@ -35,7 +35,7 @@ pub fn generate(newtype_args: &args::NewType) -> GeneratorResult<TokenStream> {
|
|||
let inner_ty = &fields.fields[0];
|
||||
let type_name = match &gql_typename {
|
||||
Some(name) => quote! { ::std::borrow::Cow::Borrowed(#name) },
|
||||
None => quote! { <#inner_ty as #crate_name::Type>::type_name() },
|
||||
None => quote! { <#inner_ty as #crate_name::InputType>::type_name() },
|
||||
};
|
||||
let create_type_info = if let Some(name) = &gql_typename {
|
||||
let specified_by_url = match &newtype_args.specified_by_url {
|
||||
|
@ -44,7 +44,7 @@ pub fn generate(newtype_args: &args::NewType) -> GeneratorResult<TokenStream> {
|
|||
};
|
||||
|
||||
quote! {
|
||||
registry.create_type::<#ident, _>(|_| #crate_name::registry::MetaType::Scalar {
|
||||
registry.create_input_type::<#ident, _>(|_| #crate_name::registry::MetaType::Scalar {
|
||||
name: ::std::borrow::ToOwned::to_owned(#name),
|
||||
description: #desc,
|
||||
is_valid: |value| <#ident as #crate_name::ScalarType>::is_valid(value),
|
||||
|
@ -53,7 +53,7 @@ pub fn generate(newtype_args: &args::NewType) -> GeneratorResult<TokenStream> {
|
|||
})
|
||||
}
|
||||
} else {
|
||||
quote! { <#inner_ty as #crate_name::Type>::create_type_info(registry) }
|
||||
quote! { <#inner_ty as #crate_name::InputType>::create_type_info(registry) }
|
||||
};
|
||||
|
||||
let expanded = quote! {
|
||||
|
@ -81,7 +81,7 @@ pub fn generate(newtype_args: &args::NewType) -> GeneratorResult<TokenStream> {
|
|||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #impl_generics #crate_name::Type for #ident #ty_generics #where_clause {
|
||||
impl #impl_generics #crate_name::InputType for #ident #ty_generics #where_clause {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
#type_name
|
||||
}
|
||||
|
@ -89,10 +89,7 @@ pub fn generate(newtype_args: &args::NewType) -> GeneratorResult<TokenStream> {
|
|||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
#create_type_info
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #impl_generics #crate_name::InputType for #ident #ty_generics #where_clause {
|
||||
fn parse(value: ::std::option::Option<#crate_name::Value>) -> #crate_name::InputValueResult<Self> {
|
||||
<#ident as #crate_name::ScalarType>::parse(value.unwrap_or_default())
|
||||
}
|
||||
|
@ -105,6 +102,14 @@ pub fn generate(newtype_args: &args::NewType) -> GeneratorResult<TokenStream> {
|
|||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #impl_generics #crate_name::OutputType for #ident #ty_generics #where_clause {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
#type_name
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
#create_type_info
|
||||
}
|
||||
|
||||
async fn resolve(
|
||||
&self,
|
||||
_: &#crate_name::ContextSelectionSet<'_>,
|
||||
|
|
|
@ -210,11 +210,11 @@ pub fn generate(
|
|||
{
|
||||
let mut key_str = Vec::new();
|
||||
#(#get_federation_key)*
|
||||
registry.add_keys(&<#entity_type as #crate_name::Type>::type_name(), &key_str.join(" "));
|
||||
registry.add_keys(&<#entity_type as #crate_name::OutputType>::type_name(), &key_str.join(" "));
|
||||
}
|
||||
});
|
||||
create_entity_types.push(
|
||||
quote! { <#entity_type as #crate_name::Type>::create_type_info(registry); },
|
||||
quote! { <#entity_type as #crate_name::OutputType>::create_type_info(registry); },
|
||||
);
|
||||
|
||||
let field_ident = &method.sig.ident;
|
||||
|
@ -241,7 +241,7 @@ pub fn generate(
|
|||
args.len(),
|
||||
quote! {
|
||||
#(#cfg_attrs)*
|
||||
if typename == &<#entity_type as #crate_name::Type>::type_name() {
|
||||
if typename == &<#entity_type as #crate_name::OutputType>::type_name() {
|
||||
if let (#(#key_pat),*) = (#(#key_getter),*) {
|
||||
let f = async move {
|
||||
#(#requires_getter)*
|
||||
|
@ -353,7 +353,7 @@ pub fn generate(
|
|||
args.insert(#name, #crate_name::registry::MetaInputValue {
|
||||
name: #name,
|
||||
description: #desc,
|
||||
ty: <#ty as #crate_name::Type>::create_type_info(registry),
|
||||
ty: <#ty as #crate_name::InputType>::create_type_info(registry),
|
||||
default_value: #schema_default,
|
||||
validator: #validator,
|
||||
visible: #visible,
|
||||
|
@ -446,7 +446,7 @@ pub fn generate(
|
|||
#(#schema_args)*
|
||||
args
|
||||
},
|
||||
ty: <#schema_ty as #crate_name::Type>::create_type_info(registry),
|
||||
ty: <#schema_ty as #crate_name::OutputType>::create_type_info(registry),
|
||||
deprecation: #field_deprecation,
|
||||
cache_control: #cache_control,
|
||||
external: #external,
|
||||
|
@ -544,34 +544,6 @@ pub fn generate(
|
|||
quote! {
|
||||
#item_impl
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #impl_generics #crate_name::Type for #self_ty #where_clause {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
let ty = registry.create_type::<Self, _>(|registry| #crate_name::registry::MetaType::Object {
|
||||
name: ::std::borrow::ToOwned::to_owned(#gql_typename),
|
||||
description: #desc,
|
||||
fields: {
|
||||
let mut fields = #crate_name::indexmap::IndexMap::new();
|
||||
#(#schema_fields)*
|
||||
fields
|
||||
},
|
||||
cache_control: #cache_control,
|
||||
extends: #extends,
|
||||
keys: ::std::option::Option::None,
|
||||
visible: #visible,
|
||||
is_subscription: false,
|
||||
rust_typename: ::std::any::type_name::<Self>(),
|
||||
});
|
||||
#(#create_entity_types)*
|
||||
#(#add_keys)*
|
||||
ty
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic, clippy::suspicious_else_formatting)]
|
||||
#[allow(unused_braces, unused_variables, unused_parens, unused_mut)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
|
@ -601,6 +573,31 @@ pub fn generate(
|
|||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#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)
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
let ty = registry.create_output_type::<Self, _>(|registry| #crate_name::registry::MetaType::Object {
|
||||
name: ::std::borrow::ToOwned::to_owned(#gql_typename),
|
||||
description: #desc,
|
||||
fields: {
|
||||
let mut fields = #crate_name::indexmap::IndexMap::new();
|
||||
#(#schema_fields)*
|
||||
fields
|
||||
},
|
||||
cache_control: #cache_control,
|
||||
extends: #extends,
|
||||
keys: ::std::option::Option::None,
|
||||
visible: #visible,
|
||||
is_subscription: false,
|
||||
rust_typename: ::std::any::type_name::<Self>(),
|
||||
});
|
||||
#(#create_entity_types)*
|
||||
#(#add_keys)*
|
||||
ty
|
||||
}
|
||||
|
||||
async fn resolve(
|
||||
&self,
|
||||
ctx: &#crate_name::ContextSelectionSet<'_>,
|
||||
|
@ -620,7 +617,7 @@ pub fn generate(
|
|||
|
||||
impl #impl_generics #self_ty #where_clause {
|
||||
fn __internal_create_type_info(registry: &mut #crate_name::registry::Registry, name: &str) -> ::std::string::String where Self: #crate_name::OutputType {
|
||||
let ty = registry.create_type::<Self, _>(|registry| #crate_name::registry::MetaType::Object {
|
||||
let ty = registry.create_output_type::<Self, _>(|registry| #crate_name::registry::MetaType::Object {
|
||||
name: ::std::borrow::ToOwned::to_owned(name),
|
||||
description: #desc,
|
||||
fields: {
|
||||
|
@ -676,17 +673,6 @@ pub fn generate(
|
|||
let concrete_type = quote! { #ty<#(#params),*> };
|
||||
|
||||
codes.push(quote! {
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::Type for #concrete_type {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
Self::__internal_create_type_info(registry, #gql_typename)
|
||||
}
|
||||
}
|
||||
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #crate_name::resolver_utils::ContainerType for #concrete_type {
|
||||
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::ServerResult<::std::option::Option<#crate_name::Value>> {
|
||||
|
@ -700,6 +686,14 @@ pub fn generate(
|
|||
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #crate_name::OutputType for #concrete_type {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
Self::__internal_create_type_info(registry, #gql_typename)
|
||||
}
|
||||
|
||||
async fn resolve(
|
||||
&self,
|
||||
ctx: &#crate_name::ContextSelectionSet<'_>,
|
||||
|
|
|
@ -39,13 +39,13 @@ pub fn generate(
|
|||
#item_impl
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #generic #crate_name::Type for #self_ty #where_clause {
|
||||
impl #generic #crate_name::InputType for #self_ty #where_clause {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
registry.create_type::<#self_ty, _>(|_| #crate_name::registry::MetaType::Scalar {
|
||||
registry.create_input_type::<#self_ty, _>(|_| #crate_name::registry::MetaType::Scalar {
|
||||
name: ::std::borrow::ToOwned::to_owned(#gql_typename),
|
||||
description: #desc,
|
||||
is_valid: |value| <#self_ty as #crate_name::ScalarType>::is_valid(value),
|
||||
|
@ -53,10 +53,7 @@ pub fn generate(
|
|||
specified_by_url: #specified_by_url,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #generic #crate_name::InputType for #self_ty #where_clause {
|
||||
fn parse(value: ::std::option::Option<#crate_name::Value>) -> #crate_name::InputValueResult<Self> {
|
||||
<#self_ty as #crate_name::ScalarType>::parse(value.unwrap_or_default())
|
||||
}
|
||||
|
@ -69,6 +66,20 @@ pub fn generate(
|
|||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #generic #crate_name::OutputType for #self_ty #where_clause {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
registry.create_output_type::<#self_ty, _>(|_| #crate_name::registry::MetaType::Scalar {
|
||||
name: ::std::borrow::ToOwned::to_owned(#gql_typename),
|
||||
description: #desc,
|
||||
is_valid: |value| <#self_ty as #crate_name::ScalarType>::is_valid(value),
|
||||
visible: #visible,
|
||||
specified_by_url: #specified_by_url,
|
||||
})
|
||||
}
|
||||
|
||||
async fn resolve(
|
||||
&self,
|
||||
_: &#crate_name::ContextSelectionSet<'_>,
|
||||
|
|
|
@ -157,7 +157,7 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
|||
name: ::std::borrow::ToOwned::to_owned(#field_name),
|
||||
description: #field_desc,
|
||||
args: ::std::default::Default::default(),
|
||||
ty: <#ty as #crate_name::Type>::create_type_info(registry),
|
||||
ty: <#ty as #crate_name::OutputType>::create_type_info(registry),
|
||||
deprecation: #field_deprecation,
|
||||
cache_control: #cache_control,
|
||||
external: #external,
|
||||
|
@ -225,7 +225,7 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
|||
});
|
||||
}
|
||||
|
||||
if !object_args.dummy && resolvers.is_empty() {
|
||||
if !object_args.fake && resolvers.is_empty() {
|
||||
return Err(Error::new_spanned(
|
||||
&ident,
|
||||
"A GraphQL Object type must define one or more fields.",
|
||||
|
@ -274,13 +274,25 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
|||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #impl_generics #crate_name::Type for #ident #ty_generics #where_clause {
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
|
||||
impl #impl_generics #crate_name::resolver_utils::ContainerType for #ident #ty_generics #where_clause {
|
||||
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::ServerResult<::std::option::Option<#crate_name::Value>> {
|
||||
#(#resolvers)*
|
||||
#complex_resolver
|
||||
::std::result::Result::Ok(::std::option::Option::None)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #impl_generics #crate_name::OutputType for #ident #ty_generics #where_clause {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
registry.create_type::<Self, _>(|registry| #crate_name::registry::MetaType::Object {
|
||||
registry.create_output_type::<Self, _>(|registry| #crate_name::registry::MetaType::Object {
|
||||
name: ::std::borrow::ToOwned::to_owned(#gql_typename),
|
||||
description: #desc,
|
||||
fields: {
|
||||
|
@ -297,22 +309,7 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
|||
rust_typename: ::std::any::type_name::<Self>(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
|
||||
impl #impl_generics #crate_name::resolver_utils::ContainerType for #ident #ty_generics #where_clause {
|
||||
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::ServerResult<::std::option::Option<#crate_name::Value>> {
|
||||
#(#resolvers)*
|
||||
#complex_resolver
|
||||
::std::result::Result::Ok(::std::option::Option::None)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #impl_generics #crate_name::OutputType for #ident #ty_generics #where_clause {
|
||||
async fn resolve(&self, ctx: &#crate_name::ContextSelectionSet<'_>, _field: &#crate_name::Positioned<#crate_name::parser::types::Field>) -> #crate_name::ServerResult<#crate_name::Value> {
|
||||
#resolve_container
|
||||
}
|
||||
|
@ -332,7 +329,7 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
|||
name: &str,
|
||||
complex_fields: #crate_name::indexmap::IndexMap<::std::string::String, #crate_name::registry::MetaField>,
|
||||
) -> ::std::string::String where Self: #crate_name::OutputType {
|
||||
registry.create_type::<Self, _>(|registry| #crate_name::registry::MetaType::Object {
|
||||
registry.create_output_type::<Self, _>(|registry| #crate_name::registry::MetaType::Object {
|
||||
name: ::std::borrow::ToOwned::to_owned(name),
|
||||
description: #desc,
|
||||
fields: {
|
||||
|
@ -363,19 +360,6 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
|||
let concrete_type = quote! { #ident<#(#params),*> };
|
||||
|
||||
let expanded = quote! {
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::Type for #concrete_type {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
let mut fields = #crate_name::indexmap::IndexMap::new();
|
||||
#concat_complex_fields
|
||||
Self::__internal_create_type_info(registry, #gql_typename, fields)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #crate_name::resolver_utils::ContainerType for #concrete_type {
|
||||
|
@ -388,6 +372,16 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
|||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #crate_name::OutputType for #concrete_type {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
let mut fields = #crate_name::indexmap::IndexMap::new();
|
||||
#concat_complex_fields
|
||||
Self::__internal_create_type_info(registry, #gql_typename, fields)
|
||||
}
|
||||
|
||||
async fn resolve(&self, ctx: &#crate_name::ContextSelectionSet<'_>, _field: &#crate_name::Positioned<#crate_name::parser::types::Field>) -> #crate_name::ServerResult<#crate_name::Value> {
|
||||
#resolve_container
|
||||
}
|
||||
|
|
|
@ -191,7 +191,7 @@ pub fn generate(
|
|||
args.insert(#name, #crate_name::registry::MetaInputValue {
|
||||
name: #name,
|
||||
description: #desc,
|
||||
ty: <#ty as #crate_name::Type>::create_type_info(registry),
|
||||
ty: <#ty as #crate_name::InputType>::create_type_info(registry),
|
||||
default_value: #schema_default,
|
||||
validator: #validator,
|
||||
visible: #visible,
|
||||
|
@ -303,7 +303,7 @@ pub fn generate(
|
|||
#(#schema_args)*
|
||||
args
|
||||
},
|
||||
ty: <<#stream_ty as #crate_name::futures_util::stream::Stream>::Item as #crate_name::Type>::create_type_info(registry),
|
||||
ty: <<#stream_ty as #crate_name::futures_util::stream::Stream>::Item as #crate_name::OutputType>::create_type_info(registry),
|
||||
deprecation: #field_deprecation,
|
||||
cache_control: ::std::default::Default::default(),
|
||||
external: false,
|
||||
|
@ -364,7 +364,7 @@ pub fn generate(
|
|||
let ri = #crate_name::extensions::ResolveInfo {
|
||||
path_node: ctx_selection_set.path_node.as_ref().unwrap(),
|
||||
parent_type: #gql_typename,
|
||||
return_type: &<<#stream_ty as #crate_name::futures_util::stream::Stream>::Item as #crate_name::Type>::qualified_type_name(),
|
||||
return_type: &<<#stream_ty as #crate_name::futures_util::stream::Stream>::Item as #crate_name::OutputType>::qualified_type_name(),
|
||||
name: field.node.name.node.as_str(),
|
||||
alias: field.node.alias.as_ref().map(|alias| alias.node.as_str()),
|
||||
};
|
||||
|
@ -437,14 +437,15 @@ pub fn generate(
|
|||
#item_impl
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #generics #crate_name::Type for #self_ty #where_clause {
|
||||
#[allow(unused_braces, unused_variables)]
|
||||
impl #generics #crate_name::SubscriptionType for #self_ty #where_clause {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
||||
#[allow(bare_trait_objects)]
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
registry.create_type::<Self, _>(|registry| #crate_name::registry::MetaType::Object {
|
||||
registry.create_subscription_type::<Self, _>(|registry| #crate_name::registry::MetaType::Object {
|
||||
name: ::std::borrow::ToOwned::to_owned(#gql_typename),
|
||||
description: #desc,
|
||||
fields: {
|
||||
|
@ -460,11 +461,7 @@ pub fn generate(
|
|||
rust_typename: ::std::any::type_name::<Self>(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[allow(unused_braces, unused_variables)]
|
||||
impl #generics #crate_name::SubscriptionType for #self_ty #where_clause {
|
||||
fn create_field_stream<'__life>(
|
||||
&'__life self,
|
||||
ctx: &'__life #crate_name::Context<'_>,
|
||||
|
|
|
@ -74,9 +74,9 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
|
|||
enum_names.push(enum_name);
|
||||
union_values.push(quote! {
|
||||
union_values.insert(
|
||||
<#p as #crate_name::Type>::type_name().into_owned(),
|
||||
<#p as #crate_name::OutputType>::type_name().into_owned(),
|
||||
#crate_name::registry::MetaUnionValue {
|
||||
name: <#p as #crate_name::Type>::type_name().into_owned(),
|
||||
name: <#p as #crate_name::OutputType>::type_name().into_owned(),
|
||||
visible: #union_visible,
|
||||
}
|
||||
);
|
||||
|
@ -119,15 +119,15 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
|
|||
|
||||
if !variant.flatten {
|
||||
registry_types.push(quote! {
|
||||
<#p as #crate_name::Type>::create_type_info(registry);
|
||||
<#p as #crate_name::OutputType>::create_type_info(registry);
|
||||
});
|
||||
possible_types.push(quote! {
|
||||
possible_types.insert(<#p as #crate_name::Type>::type_name().into_owned());
|
||||
possible_types.insert(<#p as #crate_name::OutputType>::type_name().into_owned());
|
||||
});
|
||||
} else {
|
||||
possible_types.push(quote! {
|
||||
if let #crate_name::registry::MetaType::Union { possible_types: possible_types2, .. } =
|
||||
registry.create_dummy_type::<#p>() {
|
||||
registry.create_fake_output_type::<#p>() {
|
||||
possible_types.extend(possible_types2);
|
||||
}
|
||||
});
|
||||
|
@ -135,11 +135,11 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
|
|||
|
||||
if !variant.flatten {
|
||||
get_introspection_typename.push(quote! {
|
||||
#ident::#enum_name(obj) => <#p as #crate_name::Type>::type_name()
|
||||
#ident::#enum_name(obj) => <#p as #crate_name::OutputType>::type_name()
|
||||
});
|
||||
} else {
|
||||
get_introspection_typename.push(quote! {
|
||||
#ident::#enum_name(obj) => <#p as #crate_name::Type>::introspection_type_name(obj)
|
||||
#ident::#enum_name(obj) => <#p as #crate_name::OutputType>::introspection_type_name(obj)
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -164,7 +164,23 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
|
|||
#(#type_into_impls)*
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #impl_generics #crate_name::Type for #ident #ty_generics #where_clause {
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
|
||||
impl #impl_generics #crate_name::resolver_utils::ContainerType for #ident #ty_generics #where_clause {
|
||||
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::ServerResult<::std::option::Option<#crate_name::Value>> {
|
||||
::std::result::Result::Ok(::std::option::Option::None)
|
||||
}
|
||||
|
||||
fn collect_all_fields<'__life>(&'__life self, ctx: &#crate_name::ContextSelectionSet<'__life>, fields: &mut #crate_name::resolver_utils::Fields<'__life>) -> #crate_name::ServerResult<()> {
|
||||
match self {
|
||||
#(#collect_all_fields),*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #impl_generics #crate_name::OutputType for #ident #ty_generics #where_clause {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
@ -176,7 +192,7 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
|
|||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
registry.create_type::<Self, _>(|registry| {
|
||||
registry.create_output_type::<Self, _>(|registry| {
|
||||
#(#registry_types)*
|
||||
|
||||
#crate_name::registry::MetaType::Union {
|
||||
|
@ -197,26 +213,7 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
|
|||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
|
||||
impl #impl_generics #crate_name::resolver_utils::ContainerType for #ident #ty_generics #where_clause {
|
||||
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::ServerResult<::std::option::Option<#crate_name::Value>> {
|
||||
::std::result::Result::Ok(::std::option::Option::None)
|
||||
}
|
||||
|
||||
fn collect_all_fields<'__life>(&'__life self, ctx: &#crate_name::ContextSelectionSet<'__life>, fields: &mut #crate_name::resolver_utils::Fields<'__life>) -> #crate_name::ServerResult<()> {
|
||||
match self {
|
||||
#(#collect_all_fields),*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #impl_generics #crate_name::OutputType for #ident #ty_generics #where_clause {
|
||||
async fn resolve(&self, ctx: &#crate_name::ContextSelectionSet<'_>, _field: &#crate_name::Positioned<#crate_name::parser::types::Field>) -> #crate_name::ServerResult<#crate_name::Value> {
|
||||
#crate_name::resolver_utils::resolve_container(ctx, self).await
|
||||
}
|
||||
|
|
98
src/base.rs
98
src/base.rs
|
@ -15,10 +15,35 @@ pub trait Description {
|
|||
fn description() -> &'static str;
|
||||
}
|
||||
|
||||
/// Represents a GraphQL type.
|
||||
///
|
||||
/// All GraphQL types implement this trait, such as `Scalar`, `Object`, `Union` ...
|
||||
pub trait Type {
|
||||
/// Represents a GraphQL input type.
|
||||
pub trait InputType: Send + Sync + Sized {
|
||||
/// Type the name.
|
||||
fn type_name() -> Cow<'static, str>;
|
||||
|
||||
/// Qualified typename.
|
||||
fn qualified_type_name() -> String {
|
||||
format!("{}!", Self::type_name())
|
||||
}
|
||||
|
||||
/// Create type information in the registry and return qualified typename.
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String;
|
||||
|
||||
/// Parse from `Value`. None represents undefined.
|
||||
fn parse(value: Option<Value>) -> InputValueResult<Self>;
|
||||
|
||||
/// Convert to a `Value` for introspection.
|
||||
fn to_value(&self) -> Value;
|
||||
|
||||
/// Get the federation fields, only for InputObject.
|
||||
#[doc(hidden)]
|
||||
fn federation_fields() -> Option<String> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a GraphQL output type.
|
||||
#[async_trait::async_trait]
|
||||
pub trait OutputType: Send + Sync {
|
||||
/// Type the name.
|
||||
fn type_name() -> Cow<'static, str>;
|
||||
|
||||
|
@ -36,26 +61,7 @@ pub trait Type {
|
|||
|
||||
/// Create type information in the registry and return qualified typename.
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String;
|
||||
}
|
||||
|
||||
/// Represents a GraphQL input value.
|
||||
pub trait InputType: Type + Send + Sync + Sized {
|
||||
/// Parse from `Value`. None represents undefined.
|
||||
fn parse(value: Option<Value>) -> InputValueResult<Self>;
|
||||
|
||||
/// Convert to a `Value` for introspection.
|
||||
fn to_value(&self) -> Value;
|
||||
|
||||
/// Get the federation fields, only for InputObject.
|
||||
#[doc(hidden)]
|
||||
fn federation_fields() -> Option<String> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a GraphQL output value.
|
||||
#[async_trait::async_trait]
|
||||
pub trait OutputType: Type + Send + Sync {
|
||||
/// Resolve an output value to `async_graphql::Value`.
|
||||
async fn resolve(
|
||||
&self,
|
||||
|
@ -64,7 +70,8 @@ pub trait OutputType: Type + Send + Sync {
|
|||
) -> ServerResult<Value>;
|
||||
}
|
||||
|
||||
impl<T: Type + ?Sized> Type for &T {
|
||||
#[async_trait::async_trait]
|
||||
impl<T: OutputType + ?Sized> OutputType for &T {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
T::type_name()
|
||||
}
|
||||
|
@ -72,10 +79,7 @@ impl<T: Type + ?Sized> Type for &T {
|
|||
fn create_type_info(registry: &mut Registry) -> String {
|
||||
T::create_type_info(registry)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<T: OutputType + ?Sized> OutputType for &T {
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
async fn resolve(
|
||||
&self,
|
||||
|
@ -86,22 +90,16 @@ impl<T: OutputType + ?Sized> OutputType for &T {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Type, E: Into<Error> + Send + Sync + Clone> Type for Result<T, E> {
|
||||
#[async_trait::async_trait]
|
||||
impl<T: OutputType + Sync, E: Into<Error> + Send + Sync + Clone> OutputType for Result<T, E> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
T::type_name()
|
||||
}
|
||||
|
||||
fn qualified_type_name() -> String {
|
||||
T::qualified_type_name()
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
fn create_type_info(registry: &mut Registry) -> String {
|
||||
T::create_type_info(registry)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<T: OutputType + Sync, E: Into<Error> + Send + Sync + Clone> OutputType for Result<T, E> {
|
||||
async fn resolve(
|
||||
&self,
|
||||
ctx: &ContextSelectionSet<'_>,
|
||||
|
@ -131,7 +129,8 @@ pub trait UnionType: ContainerType {}
|
|||
/// A GraphQL input object.
|
||||
pub trait InputObjectType: InputType {}
|
||||
|
||||
impl<T: Type + ?Sized> Type for Box<T> {
|
||||
#[async_trait::async_trait]
|
||||
impl<T: OutputType + ?Sized> OutputType for Box<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
T::type_name()
|
||||
}
|
||||
|
@ -139,10 +138,7 @@ impl<T: Type + ?Sized> Type for Box<T> {
|
|||
fn create_type_info(registry: &mut Registry) -> String {
|
||||
T::create_type_info(registry)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<T: OutputType + ?Sized> OutputType for Box<T> {
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
async fn resolve(
|
||||
&self,
|
||||
|
@ -155,6 +151,14 @@ impl<T: OutputType + ?Sized> OutputType for Box<T> {
|
|||
|
||||
#[async_trait::async_trait]
|
||||
impl<T: InputType> InputType for Box<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
T::type_name()
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut Registry) -> String {
|
||||
T::create_type_info(registry)
|
||||
}
|
||||
|
||||
fn parse(value: Option<ConstValue>) -> InputValueResult<Self> {
|
||||
T::parse(value)
|
||||
.map(Box::new)
|
||||
|
@ -166,7 +170,8 @@ impl<T: InputType> InputType for Box<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Type + ?Sized> Type for Arc<T> {
|
||||
#[async_trait::async_trait]
|
||||
impl<T: OutputType + ?Sized> OutputType for Arc<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
T::type_name()
|
||||
}
|
||||
|
@ -174,10 +179,7 @@ impl<T: Type + ?Sized> Type for Arc<T> {
|
|||
fn create_type_info(registry: &mut Registry) -> String {
|
||||
T::create_type_info(registry)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<T: OutputType + ?Sized> OutputType for Arc<T> {
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
async fn resolve(
|
||||
&self,
|
||||
|
@ -189,6 +191,14 @@ impl<T: OutputType + ?Sized> OutputType for Arc<T> {
|
|||
}
|
||||
|
||||
impl<T: InputType> InputType for Arc<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
T::type_name()
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut Registry) -> String {
|
||||
T::create_type_info(registry)
|
||||
}
|
||||
|
||||
fn parse(value: Option<ConstValue>) -> InputValueResult<Self> {
|
||||
T::parse(value)
|
||||
.map(Arc::new)
|
||||
|
|
|
@ -206,7 +206,7 @@ pub use async_graphql_value::{
|
|||
};
|
||||
pub use base::{
|
||||
ComplexObject, Description, InputObjectType, InputType, InterfaceType, ObjectType, OutputType,
|
||||
Type, UnionType,
|
||||
UnionType,
|
||||
};
|
||||
pub use error::{
|
||||
Error, ErrorExtensionValues, ErrorExtensions, InputValueError, InputValueResult,
|
||||
|
|
|
@ -12,7 +12,10 @@ use crate::parser::types::{
|
|||
BaseType as ParsedBaseType, Field, Type as ParsedType, VariableDefinition,
|
||||
};
|
||||
use crate::validators::InputValueValidator;
|
||||
use crate::{model, Any, Context, Positioned, ServerResult, Type, Value, VisitorContext};
|
||||
use crate::{
|
||||
model, Any, Context, InputType, OutputType, Positioned, ServerResult, SubscriptionType, Value,
|
||||
VisitorContext,
|
||||
};
|
||||
|
||||
pub use cache_control::CacheControl;
|
||||
|
||||
|
@ -375,15 +378,41 @@ pub struct Registry {
|
|||
}
|
||||
|
||||
impl Registry {
|
||||
pub fn create_type<T: crate::Type + ?Sized, F: FnMut(&mut Registry) -> MetaType>(
|
||||
pub fn create_input_type<T: InputType + ?Sized, F: FnMut(&mut Registry) -> MetaType>(
|
||||
&mut self,
|
||||
mut f: F,
|
||||
) -> String {
|
||||
let name = T::type_name();
|
||||
self.create_type(&mut f, &*T::type_name(), std::any::type_name::<T>());
|
||||
T::qualified_type_name()
|
||||
}
|
||||
|
||||
match self.types.get(name.as_ref()) {
|
||||
pub fn create_output_type<T: OutputType + ?Sized, F: FnMut(&mut Registry) -> MetaType>(
|
||||
&mut self,
|
||||
mut f: F,
|
||||
) -> String {
|
||||
self.create_type(&mut f, &*T::type_name(), std::any::type_name::<T>());
|
||||
T::qualified_type_name()
|
||||
}
|
||||
|
||||
pub fn create_subscription_type<
|
||||
T: SubscriptionType + ?Sized,
|
||||
F: FnMut(&mut Registry) -> MetaType,
|
||||
>(
|
||||
&mut self,
|
||||
mut f: F,
|
||||
) -> String {
|
||||
self.create_type(&mut f, &*T::type_name(), std::any::type_name::<T>());
|
||||
T::qualified_type_name()
|
||||
}
|
||||
|
||||
fn create_type<F: FnMut(&mut Registry) -> MetaType>(
|
||||
&mut self,
|
||||
f: &mut F,
|
||||
name: &str,
|
||||
rust_typename: &str,
|
||||
) {
|
||||
match self.types.get(name) {
|
||||
Some(ty) => {
|
||||
let rust_typename = std::any::type_name::<T>();
|
||||
if let Some(prev_typename) = ty.rust_typename() {
|
||||
if prev_typename != "__fake_type__" && rust_typename != prev_typename {
|
||||
panic!(
|
||||
|
@ -396,7 +425,7 @@ impl Registry {
|
|||
None => {
|
||||
// Inserting a fake type before calling the function allows recursive types to exist.
|
||||
self.types.insert(
|
||||
name.clone().into_owned(),
|
||||
name.to_string(),
|
||||
MetaType::Object {
|
||||
name: "".to_string(),
|
||||
description: None,
|
||||
|
@ -413,11 +442,25 @@ impl Registry {
|
|||
*self.types.get_mut(&*name).unwrap() = ty;
|
||||
}
|
||||
}
|
||||
|
||||
T::qualified_type_name()
|
||||
}
|
||||
|
||||
pub fn create_dummy_type<T: Type>(&mut self) -> MetaType {
|
||||
pub fn create_fake_output_type<T: OutputType>(&mut self) -> MetaType {
|
||||
T::create_type_info(self);
|
||||
self.types
|
||||
.get(&*T::type_name())
|
||||
.cloned()
|
||||
.expect("You definitely encountered a bug!")
|
||||
}
|
||||
|
||||
pub fn create_fake_input_type<T: InputType>(&mut self) -> MetaType {
|
||||
T::create_type_info(self);
|
||||
self.types
|
||||
.get(&*T::type_name())
|
||||
.cloned()
|
||||
.expect("You definitely encountered a bug!")
|
||||
}
|
||||
|
||||
pub fn create_fake_subscription_type<T: SubscriptionType>(&mut self) -> MetaType {
|
||||
T::create_type_info(self);
|
||||
self.types
|
||||
.get(&*T::type_name())
|
||||
|
@ -512,7 +555,7 @@ impl Registry {
|
|||
}
|
||||
|
||||
pub(crate) fn create_federation_types(&mut self) {
|
||||
Any::create_type_info(self);
|
||||
<Any as InputType>::create_type_info(self);
|
||||
|
||||
self.types.insert(
|
||||
"_Service".to_string(),
|
||||
|
@ -647,8 +690,8 @@ impl Registry {
|
|||
names.into_iter().collect()
|
||||
}
|
||||
|
||||
pub fn set_description<T: Type>(&mut self, desc: &'static str) {
|
||||
match self.types.get_mut(&*T::type_name()) {
|
||||
pub fn set_description(&mut self, name: &str, desc: &'static str) {
|
||||
match self.types.get_mut(name) {
|
||||
Some(MetaType::Scalar { description, .. }) => *description = Some(desc),
|
||||
Some(MetaType::Object { description, .. }) => *description = Some(desc),
|
||||
Some(MetaType::Interface { description, .. }) => *description = Some(desc),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{InputType, InputValueError, InputValueResult, Name, Type, Value};
|
||||
use crate::{InputType, InputValueError, InputValueResult, Name, Value};
|
||||
|
||||
/// A variant of an enum.
|
||||
pub struct EnumItem<T> {
|
||||
|
@ -9,7 +9,7 @@ pub struct EnumItem<T> {
|
|||
}
|
||||
|
||||
/// A GraphQL enum.
|
||||
pub trait EnumType: Type + Sized + Eq + Send + Copy + Sized + 'static {
|
||||
pub trait EnumType: Sized + Eq + Send + Copy + Sized + 'static {
|
||||
/// Get a list of possible variants of the enum and their values.
|
||||
fn items() -> &'static [EnumItem<Self>];
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::extensions::ResolveInfo;
|
||||
use crate::parser::types::Field;
|
||||
use crate::{ContextSelectionSet, OutputType, Positioned, ServerResult, Type, Value};
|
||||
use crate::{ContextSelectionSet, OutputType, Positioned, ServerResult, Value};
|
||||
|
||||
/// Resolve an list by executing each of the items concurrently.
|
||||
pub async fn resolve_list<'a, T: OutputType + 'a>(
|
||||
|
|
|
@ -136,24 +136,6 @@ macro_rules! scalar {
|
|||
#[doc(hidden)]
|
||||
macro_rules! scalar_internal {
|
||||
($ty:ty, $name:expr, $desc:expr, $specified_by_url:expr) => {
|
||||
impl $crate::Type for $ty {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed($name)
|
||||
}
|
||||
|
||||
fn create_type_info(
|
||||
registry: &mut $crate::registry::Registry,
|
||||
) -> ::std::string::String {
|
||||
registry.create_type::<$ty, _>(|_| $crate::registry::MetaType::Scalar {
|
||||
name: ::std::borrow::ToOwned::to_owned($name),
|
||||
description: $desc,
|
||||
is_valid: |value| <$ty as $crate::ScalarType>::is_valid(value),
|
||||
visible: ::std::option::Option::None,
|
||||
specified_by_url: $specified_by_url,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::ScalarType for $ty {
|
||||
fn parse(value: $crate::Value) -> $crate::InputValueResult<Self> {
|
||||
::std::result::Result::Ok($crate::from_value(value)?)
|
||||
|
@ -165,6 +147,22 @@ macro_rules! scalar_internal {
|
|||
}
|
||||
|
||||
impl $crate::InputType for $ty {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed($name)
|
||||
}
|
||||
|
||||
fn create_type_info(
|
||||
registry: &mut $crate::registry::Registry,
|
||||
) -> ::std::string::String {
|
||||
registry.create_input_type::<$ty, _>(|_| $crate::registry::MetaType::Scalar {
|
||||
name: ::std::borrow::ToOwned::to_owned($name),
|
||||
description: $desc,
|
||||
is_valid: |value| <$ty as $crate::ScalarType>::is_valid(value),
|
||||
visible: ::std::option::Option::None,
|
||||
specified_by_url: $specified_by_url,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse(
|
||||
value: ::std::option::Option<$crate::Value>,
|
||||
) -> $crate::InputValueResult<Self> {
|
||||
|
@ -178,6 +176,22 @@ macro_rules! scalar_internal {
|
|||
|
||||
#[$crate::async_trait::async_trait]
|
||||
impl $crate::OutputType for $ty {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed($name)
|
||||
}
|
||||
|
||||
fn create_type_info(
|
||||
registry: &mut $crate::registry::Registry,
|
||||
) -> ::std::string::String {
|
||||
registry.create_output_type::<$ty, _>(|_| $crate::registry::MetaType::Scalar {
|
||||
name: ::std::borrow::ToOwned::to_owned($name),
|
||||
description: $desc,
|
||||
is_valid: |value| <$ty as $crate::ScalarType>::is_valid(value),
|
||||
visible: ::std::option::Option::None,
|
||||
specified_by_url: $specified_by_url,
|
||||
})
|
||||
}
|
||||
|
||||
async fn resolve(
|
||||
&self,
|
||||
_: &$crate::ContextSelectionSet<'_>,
|
||||
|
|
|
@ -16,8 +16,8 @@ use crate::subscription::collect_subscription_streams;
|
|||
use crate::types::QueryRoot;
|
||||
use crate::validation::{check_rules, ValidationMode};
|
||||
use crate::{
|
||||
BatchRequest, BatchResponse, CacheControl, ContextBase, ObjectType, QueryEnv, Request,
|
||||
Response, ServerError, SubscriptionType, Type, ID,
|
||||
BatchRequest, BatchResponse, CacheControl, ContextBase, InputType, ObjectType, OutputType,
|
||||
QueryEnv, Request, Response, ServerError, SubscriptionType, ID,
|
||||
};
|
||||
|
||||
/// Schema builder
|
||||
|
@ -34,10 +34,18 @@ pub struct SchemaBuilder<Query, Mutation, Subscription> {
|
|||
}
|
||||
|
||||
impl<Query, Mutation, Subscription> SchemaBuilder<Query, Mutation, Subscription> {
|
||||
/// Manually register a type in the schema.
|
||||
/// Manually register a input type in the schema.
|
||||
///
|
||||
/// You can use this function to register schema types that are not directly referenced.
|
||||
pub fn register_type<T: Type>(mut self) -> Self {
|
||||
pub fn register_input_type<T: InputType>(mut self) -> Self {
|
||||
T::create_type_info(&mut self.registry);
|
||||
self
|
||||
}
|
||||
|
||||
/// Manually register a output type in the schema.
|
||||
///
|
||||
/// You can use this function to register schema types that are not directly referenced.
|
||||
pub fn register_output_type<T: OutputType>(mut self) -> Self {
|
||||
T::create_type_info(&mut self.registry);
|
||||
self
|
||||
}
|
||||
|
@ -111,9 +119,15 @@ impl<Query, Mutation, Subscription> SchemaBuilder<Query, Mutation, Subscription>
|
|||
self
|
||||
}
|
||||
|
||||
/// Override the name of the specified type.
|
||||
pub fn override_description<T: Type>(mut self, desc: &'static str) -> Self {
|
||||
self.registry.set_description::<T>(desc);
|
||||
/// Override the name of the specified input type.
|
||||
pub fn override_input_type_description<T: InputType>(mut self, desc: &'static str) -> Self {
|
||||
self.registry.set_description(&*T::type_name(), desc);
|
||||
self
|
||||
}
|
||||
|
||||
/// Override the name of the specified output type.
|
||||
pub fn override_output_type_description<T: OutputType>(mut self, desc: &'static str) -> Self {
|
||||
self.registry.set_description(&*T::type_name(), desc);
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -308,11 +322,11 @@ where
|
|||
});
|
||||
|
||||
// register scalars
|
||||
bool::create_type_info(&mut registry);
|
||||
i32::create_type_info(&mut registry);
|
||||
f32::create_type_info(&mut registry);
|
||||
String::create_type_info(&mut registry);
|
||||
ID::create_type_info(&mut registry);
|
||||
<bool as InputType>::create_type_info(&mut registry);
|
||||
<i32 as InputType>::create_type_info(&mut registry);
|
||||
<f32 as InputType>::create_type_info(&mut registry);
|
||||
<String as InputType>::create_type_info(&mut registry);
|
||||
<ID as InputType>::create_type_info(&mut registry);
|
||||
|
||||
QueryRoot::<Query>::create_type_info(&mut registry);
|
||||
if !Mutation::is_empty() {
|
||||
|
|
|
@ -1,12 +1,27 @@
|
|||
use std::borrow::Cow;
|
||||
use std::pin::Pin;
|
||||
|
||||
use futures_util::stream::{Stream, StreamExt};
|
||||
|
||||
use crate::parser::types::{Selection, TypeCondition};
|
||||
use crate::{Context, ContextSelectionSet, PathSegment, Response, ServerError, ServerResult, Type};
|
||||
use crate::registry::Registry;
|
||||
use crate::{
|
||||
registry, Context, ContextSelectionSet, PathSegment, Response, ServerError, ServerResult,
|
||||
};
|
||||
|
||||
/// A GraphQL subscription object
|
||||
pub trait SubscriptionType: Type + Send + Sync {
|
||||
pub trait SubscriptionType: Send + Sync {
|
||||
/// Type the name.
|
||||
fn type_name() -> Cow<'static, str>;
|
||||
|
||||
/// Qualified typename.
|
||||
fn qualified_type_name() -> String {
|
||||
format!("{}!", Self::type_name())
|
||||
}
|
||||
|
||||
/// Create type information in the registry and return qualified typename.
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String;
|
||||
|
||||
/// This function returns true of type `EmptySubscription` only.
|
||||
#[doc(hidden)]
|
||||
fn is_empty() -> bool {
|
||||
|
@ -90,6 +105,14 @@ pub(crate) fn collect_subscription_streams<'a, T: SubscriptionType + 'static>(
|
|||
}
|
||||
|
||||
impl<T: SubscriptionType> SubscriptionType for &T {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
T::type_name()
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut Registry) -> String {
|
||||
T::create_type_info(registry)
|
||||
}
|
||||
|
||||
fn create_field_stream<'a>(
|
||||
&'a self,
|
||||
ctx: &'a Context<'_>,
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::resolver_utils::{resolve_container, ContainerType};
|
|||
use crate::types::connection::{CursorType, EmptyFields};
|
||||
use crate::{
|
||||
registry, Context, ContextSelectionSet, ObjectType, OutputType, Positioned, Result,
|
||||
ServerResult, Type, Value,
|
||||
ServerResult, Value,
|
||||
};
|
||||
|
||||
/// Connection type
|
||||
|
@ -119,84 +119,6 @@ impl<C, T, EC, EE> Connection<C, T, EC, EE> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<C, T, EC, EE> Type for Connection<C, T, EC, EE>
|
||||
where
|
||||
C: CursorType,
|
||||
T: OutputType,
|
||||
EC: ObjectType,
|
||||
EE: ObjectType,
|
||||
{
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Owned(format!("{}Connection", T::type_name()))
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
registry.create_type::<Self, _>(|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,
|
||||
},
|
||||
);
|
||||
|
||||
fields.insert(
|
||||
"edges".to_string(),
|
||||
registry::MetaField {
|
||||
name: "edges".to_string(),
|
||||
description: Some("A list of edges."),
|
||||
args: Default::default(),
|
||||
ty: <Option<Vec<Option<Edge<C, T, EE>>>> as Type>::create_type_info(
|
||||
registry,
|
||||
),
|
||||
deprecation: Default::default(),
|
||||
cache_control: Default::default(),
|
||||
external: false,
|
||||
requires: None,
|
||||
provides: None,
|
||||
visible: None,
|
||||
compute_complexity: None,
|
||||
},
|
||||
);
|
||||
|
||||
fields.extend(additional_fields);
|
||||
fields
|
||||
},
|
||||
cache_control: Default::default(),
|
||||
extends: false,
|
||||
keys: None,
|
||||
visible: None,
|
||||
is_subscription: false,
|
||||
rust_typename: std::any::type_name::<Self>(),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<C, T, EC, EE> ContainerType for Connection<C, T, EC, EE>
|
||||
where
|
||||
|
@ -236,6 +158,76 @@ where
|
|||
EC: ObjectType,
|
||||
EE: ObjectType,
|
||||
{
|
||||
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::<Self, _>(|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,
|
||||
},
|
||||
);
|
||||
|
||||
fields.insert(
|
||||
"edges".to_string(),
|
||||
registry::MetaField {
|
||||
name: "edges".to_string(),
|
||||
description: Some("A list of edges."),
|
||||
args: Default::default(),
|
||||
ty: <Option<Vec<Option<Edge<C, T, EE>>>> as OutputType>::create_type_info(
|
||||
registry,
|
||||
),
|
||||
deprecation: Default::default(),
|
||||
cache_control: Default::default(),
|
||||
external: false,
|
||||
requires: None,
|
||||
provides: None,
|
||||
visible: None,
|
||||
compute_complexity: None,
|
||||
},
|
||||
);
|
||||
|
||||
fields.extend(additional_fields);
|
||||
fields
|
||||
},
|
||||
cache_control: Default::default(),
|
||||
extends: false,
|
||||
keys: None,
|
||||
visible: None,
|
||||
is_subscription: false,
|
||||
rust_typename: std::any::type_name::<Self>(),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async fn resolve(
|
||||
&self,
|
||||
ctx: &ContextSelectionSet<'_>,
|
||||
|
|
|
@ -7,8 +7,7 @@ use crate::parser::types::Field;
|
|||
use crate::resolver_utils::{resolve_container, ContainerType};
|
||||
use crate::types::connection::CursorType;
|
||||
use crate::{
|
||||
registry, Context, ContextSelectionSet, ObjectType, OutputType, Positioned, ServerResult, Type,
|
||||
Value,
|
||||
registry, Context, ContextSelectionSet, ObjectType, OutputType, Positioned, ServerResult, Value,
|
||||
};
|
||||
|
||||
/// The edge type output by the data source
|
||||
|
@ -40,9 +39,31 @@ impl<C: CursorType, T> Edge<C, T, EmptyFields> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<C, T, E> Type for Edge<C, T, E>
|
||||
#[async_trait::async_trait]
|
||||
impl<C, T, E> ContainerType for Edge<C, T, E>
|
||||
where
|
||||
C: CursorType,
|
||||
C: CursorType + Send + Sync,
|
||||
T: OutputType,
|
||||
E: ObjectType,
|
||||
{
|
||||
async fn resolve_field(&self, ctx: &Context<'_>) -> ServerResult<Option<Value>> {
|
||||
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<C, T, E> OutputType for Edge<C, T, E>
|
||||
where
|
||||
C: CursorType + Send + Sync,
|
||||
T: OutputType,
|
||||
E: ObjectType,
|
||||
{
|
||||
|
@ -51,9 +72,9 @@ where
|
|||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
registry.create_type::<Self, _>(|registry| {
|
||||
registry.create_output_type::<Self, _>(|registry| {
|
||||
let additional_fields = if let registry::MetaType::Object { fields, .. } =
|
||||
registry.create_dummy_type::<E>()
|
||||
registry.create_fake_output_type::<E>()
|
||||
{
|
||||
fields
|
||||
} else {
|
||||
|
@ -112,36 +133,7 @@ where
|
|||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<C, T, E> ContainerType for Edge<C, T, E>
|
||||
where
|
||||
C: CursorType + Send + Sync,
|
||||
T: OutputType,
|
||||
E: ObjectType,
|
||||
{
|
||||
async fn resolve_field(&self, ctx: &Context<'_>) -> ServerResult<Option<Value>> {
|
||||
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<C, T, E> OutputType for Edge<C, T, E>
|
||||
where
|
||||
C: CursorType + Send + Sync,
|
||||
T: OutputType,
|
||||
E: ObjectType,
|
||||
{
|
||||
async fn resolve(
|
||||
&self,
|
||||
ctx: &ContextSelectionSet<'_>,
|
||||
|
|
|
@ -16,7 +16,7 @@ pub use page_info::PageInfo;
|
|||
|
||||
/// Empty additional fields
|
||||
#[derive(SimpleObject)]
|
||||
#[graphql(internal, dummy)]
|
||||
#[graphql(internal, fake)]
|
||||
pub struct EmptyFields;
|
||||
|
||||
/// Parses the parameters and executes the query.
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::parser::types::Field;
|
|||
use crate::resolver_utils::ContainerType;
|
||||
use crate::{
|
||||
registry, Context, ContextSelectionSet, ObjectType, OutputType, Positioned, ServerError,
|
||||
ServerResult, Type, Value,
|
||||
ServerResult, Value,
|
||||
};
|
||||
|
||||
/// Empty mutation
|
||||
|
@ -31,26 +31,6 @@ use crate::{
|
|||
#[derive(Default, Copy, Clone)]
|
||||
pub struct EmptyMutation;
|
||||
|
||||
impl Type for EmptyMutation {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Borrowed("EmptyMutation")
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
registry.create_type::<Self, _>(|_| registry::MetaType::Object {
|
||||
name: "EmptyMutation".to_string(),
|
||||
description: None,
|
||||
fields: Default::default(),
|
||||
cache_control: Default::default(),
|
||||
extends: false,
|
||||
keys: None,
|
||||
visible: None,
|
||||
is_subscription: false,
|
||||
rust_typename: std::any::type_name::<Self>(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl ContainerType for EmptyMutation {
|
||||
fn is_empty() -> bool {
|
||||
|
@ -64,6 +44,24 @@ impl ContainerType for EmptyMutation {
|
|||
|
||||
#[async_trait::async_trait]
|
||||
impl OutputType for EmptyMutation {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Borrowed("EmptyMutation")
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
registry.create_output_type::<Self, _>(|_| registry::MetaType::Object {
|
||||
name: "EmptyMutation".to_string(),
|
||||
description: None,
|
||||
fields: Default::default(),
|
||||
cache_control: Default::default(),
|
||||
extends: false,
|
||||
keys: None,
|
||||
visible: None,
|
||||
is_subscription: false,
|
||||
rust_typename: std::any::type_name::<Self>(),
|
||||
})
|
||||
}
|
||||
|
||||
async fn resolve(
|
||||
&self,
|
||||
_ctx: &ContextSelectionSet<'_>,
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::pin::Pin;
|
|||
|
||||
use futures_util::stream::{self, Stream};
|
||||
|
||||
use crate::{registry, Context, Response, ServerError, SubscriptionType, Type};
|
||||
use crate::{registry, Context, Response, ServerError, SubscriptionType};
|
||||
|
||||
/// Empty subscription
|
||||
///
|
||||
|
@ -11,13 +11,13 @@ use crate::{registry, Context, Response, ServerError, SubscriptionType, Type};
|
|||
#[derive(Default, Copy, Clone)]
|
||||
pub struct EmptySubscription;
|
||||
|
||||
impl Type for EmptySubscription {
|
||||
impl SubscriptionType for EmptySubscription {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Borrowed("EmptyMutation")
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
registry.create_type::<Self, _>(|_| registry::MetaType::Object {
|
||||
registry.create_subscription_type::<Self, _>(|_| registry::MetaType::Object {
|
||||
name: "EmptySubscription".to_string(),
|
||||
description: None,
|
||||
fields: Default::default(),
|
||||
|
@ -29,9 +29,7 @@ impl Type for EmptySubscription {
|
|||
rust_typename: std::any::type_name::<Self>(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl SubscriptionType for EmptySubscription {
|
||||
fn is_empty() -> bool {
|
||||
true
|
||||
}
|
||||
|
|
|
@ -1,28 +1,22 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use bytes::Bytes;
|
||||
|
||||
use crate::parser::types::Field;
|
||||
use crate::parser::Positioned;
|
||||
use crate::{registry, ContextSelectionSet, OutputType, ServerResult, Type, Value};
|
||||
use crate::{InputValueError, InputValueResult, Scalar, ScalarType, Value};
|
||||
|
||||
impl Type for Bytes {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Borrowed("Binary")
|
||||
/// The `Binary` scalar type represents binary data.
|
||||
#[Scalar(internal)]
|
||||
impl ScalarType for Bytes {
|
||||
fn parse(value: Value) -> InputValueResult<Self> {
|
||||
match value {
|
||||
Value::Binary(data) => Ok(data),
|
||||
_ => Err(InputValueError::expected_type(value)),
|
||||
}
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
<String as Type>::create_type_info(registry)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl OutputType for Bytes {
|
||||
async fn resolve(
|
||||
&self,
|
||||
_: &ContextSelectionSet<'_>,
|
||||
_field: &Positioned<Field>,
|
||||
) -> ServerResult<Value> {
|
||||
Ok(Value::Binary(self.clone()))
|
||||
fn is_valid(value: &Value) -> bool {
|
||||
matches!(value, Value::Binary(_))
|
||||
}
|
||||
|
||||
fn to_value(&self) -> Value {
|
||||
Value::Binary(self.clone())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,20 +2,7 @@ use std::borrow::Cow;
|
|||
|
||||
use async_graphql_parser::types::Field;
|
||||
|
||||
use crate::{registry, ContextSelectionSet, OutputType, Positioned, ServerResult, Type, Value};
|
||||
|
||||
impl<'a, T> Type for Cow<'a, T>
|
||||
where
|
||||
T: Type + ToOwned + ?Sized + Send + Sync,
|
||||
{
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
T::type_name()
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
<T as Type>::create_type_info(registry)
|
||||
}
|
||||
}
|
||||
use crate::{registry, ContextSelectionSet, OutputType, Positioned, ServerResult, Value};
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<'a, T> OutputType for Cow<'a, T>
|
||||
|
@ -23,6 +10,14 @@ where
|
|||
T: OutputType + ToOwned + ?Sized,
|
||||
<T as ToOwned>::Owned: Send + Sync,
|
||||
{
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
T::type_name()
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
<T as OutputType>::create_type_info(registry)
|
||||
}
|
||||
|
||||
async fn resolve(
|
||||
&self,
|
||||
ctx: &ContextSelectionSet<'_>,
|
||||
|
|
|
@ -4,10 +4,10 @@ use crate::parser::types::Field;
|
|||
use crate::resolver_utils::resolve_list;
|
||||
use crate::{
|
||||
registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, OutputType,
|
||||
Positioned, ServerResult, Type, Value,
|
||||
Positioned, ServerResult, Value,
|
||||
};
|
||||
|
||||
impl<T: Type, const N: usize> Type for [T; N] {
|
||||
impl<T: InputType, const N: usize> InputType for [T; N] {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Owned(format!("[{}]", T::qualified_type_name()))
|
||||
}
|
||||
|
@ -20,9 +20,7 @@ impl<T: Type, const N: usize> Type for [T; N] {
|
|||
T::create_type_info(registry);
|
||||
Self::qualified_type_name()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: InputType, const N: usize> InputType for [T; N] {
|
||||
fn parse(value: Option<Value>) -> InputValueResult<Self> {
|
||||
if let Some(Value::List(values)) = value {
|
||||
let items: Vec<T> = values
|
||||
|
@ -52,6 +50,19 @@ impl<T: InputType, const N: usize> InputType for [T; N] {
|
|||
|
||||
#[async_trait::async_trait]
|
||||
impl<T: OutputType, const N: usize> OutputType for [T; N] {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Owned(format!("[{}]", T::qualified_type_name()))
|
||||
}
|
||||
|
||||
fn qualified_type_name() -> String {
|
||||
format!("[{}]!", T::qualified_type_name())
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
T::create_type_info(registry);
|
||||
Self::qualified_type_name()
|
||||
}
|
||||
|
||||
async fn resolve(
|
||||
&self,
|
||||
ctx: &ContextSelectionSet<'_>,
|
||||
|
|
|
@ -5,10 +5,10 @@ use crate::parser::types::Field;
|
|||
use crate::resolver_utils::resolve_list;
|
||||
use crate::{
|
||||
registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, OutputType,
|
||||
Positioned, ServerResult, Type, Value,
|
||||
Positioned, ServerResult, Value,
|
||||
};
|
||||
|
||||
impl<T: Type> Type for BTreeSet<T> {
|
||||
impl<T: InputType + Ord> InputType for BTreeSet<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Owned(format!("[{}]", T::qualified_type_name()))
|
||||
}
|
||||
|
@ -21,9 +21,7 @@ impl<T: Type> Type for BTreeSet<T> {
|
|||
T::create_type_info(registry);
|
||||
Self::qualified_type_name()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: InputType + Ord> InputType for BTreeSet<T> {
|
||||
fn parse(value: Option<Value>) -> InputValueResult<Self> {
|
||||
match value.unwrap_or_default() {
|
||||
Value::List(values) => values
|
||||
|
@ -46,6 +44,19 @@ impl<T: InputType + Ord> InputType for BTreeSet<T> {
|
|||
|
||||
#[async_trait::async_trait]
|
||||
impl<T: OutputType + Ord> OutputType for BTreeSet<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Owned(format!("[{}]", T::qualified_type_name()))
|
||||
}
|
||||
|
||||
fn qualified_type_name() -> String {
|
||||
format!("[{}]!", T::qualified_type_name())
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
T::create_type_info(registry);
|
||||
Self::qualified_type_name()
|
||||
}
|
||||
|
||||
async fn resolve(
|
||||
&self,
|
||||
ctx: &ContextSelectionSet<'_>,
|
||||
|
|
|
@ -7,10 +7,10 @@ use crate::parser::types::Field;
|
|||
use crate::resolver_utils::resolve_list;
|
||||
use crate::{
|
||||
registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, OutputType,
|
||||
Positioned, Result, ServerResult, Type, Value,
|
||||
Positioned, Result, ServerResult, Value,
|
||||
};
|
||||
|
||||
impl<T: Type> Type for HashSet<T> {
|
||||
impl<T: InputType + Hash + Eq> InputType for HashSet<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Owned(format!("[{}]", T::qualified_type_name()))
|
||||
}
|
||||
|
@ -23,9 +23,7 @@ impl<T: Type> Type for HashSet<T> {
|
|||
T::create_type_info(registry);
|
||||
Self::qualified_type_name()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: InputType + Hash + Eq> InputType for HashSet<T> {
|
||||
fn parse(value: Option<Value>) -> InputValueResult<Self> {
|
||||
match value.unwrap_or_default() {
|
||||
Value::List(values) => values
|
||||
|
@ -48,6 +46,19 @@ impl<T: InputType + Hash + Eq> InputType for HashSet<T> {
|
|||
|
||||
#[async_trait::async_trait]
|
||||
impl<T: OutputType + Hash + Eq> OutputType for HashSet<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Owned(format!("[{}]", T::qualified_type_name()))
|
||||
}
|
||||
|
||||
fn qualified_type_name() -> String {
|
||||
format!("[{}]!", T::qualified_type_name())
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
T::create_type_info(registry);
|
||||
Self::qualified_type_name()
|
||||
}
|
||||
|
||||
async fn resolve(
|
||||
&self,
|
||||
ctx: &ContextSelectionSet<'_>,
|
||||
|
|
|
@ -5,10 +5,10 @@ use crate::parser::types::Field;
|
|||
use crate::resolver_utils::resolve_list;
|
||||
use crate::{
|
||||
registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, OutputType,
|
||||
Positioned, ServerResult, Type, Value,
|
||||
Positioned, ServerResult, Value,
|
||||
};
|
||||
|
||||
impl<T: Type> Type for LinkedList<T> {
|
||||
impl<T: InputType> InputType for LinkedList<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Owned(format!("[{}]", T::qualified_type_name()))
|
||||
}
|
||||
|
@ -21,9 +21,7 @@ impl<T: Type> Type for LinkedList<T> {
|
|||
T::create_type_info(registry);
|
||||
Self::qualified_type_name()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: InputType> InputType for LinkedList<T> {
|
||||
fn parse(value: Option<Value>) -> InputValueResult<Self> {
|
||||
match value.unwrap_or_default() {
|
||||
Value::List(values) => values
|
||||
|
@ -47,6 +45,19 @@ impl<T: InputType> InputType for LinkedList<T> {
|
|||
|
||||
#[async_trait::async_trait]
|
||||
impl<T: OutputType> OutputType for LinkedList<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Owned(format!("[{}]", T::qualified_type_name()))
|
||||
}
|
||||
|
||||
fn qualified_type_name() -> String {
|
||||
format!("[{}]!", T::qualified_type_name())
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
T::create_type_info(registry);
|
||||
Self::qualified_type_name()
|
||||
}
|
||||
|
||||
async fn resolve(
|
||||
&self,
|
||||
ctx: &ContextSelectionSet<'_>,
|
||||
|
|
|
@ -2,9 +2,10 @@ use std::borrow::Cow;
|
|||
|
||||
use crate::parser::types::Field;
|
||||
use crate::resolver_utils::resolve_list;
|
||||
use crate::{registry, ContextSelectionSet, OutputType, Positioned, ServerResult, Type, Value};
|
||||
use crate::{registry, ContextSelectionSet, OutputType, Positioned, ServerResult, Value};
|
||||
|
||||
impl<'a, T: Type + 'a> Type for &'a [T] {
|
||||
#[async_trait::async_trait]
|
||||
impl<'a, T: OutputType + 'a> OutputType for &'a [T] {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Owned(format!("[{}]", T::qualified_type_name()))
|
||||
}
|
||||
|
@ -17,10 +18,7 @@ impl<'a, T: Type + 'a> Type for &'a [T] {
|
|||
T::create_type_info(registry);
|
||||
Self::qualified_type_name()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<T: OutputType> OutputType for &[T] {
|
||||
async fn resolve(
|
||||
&self,
|
||||
ctx: &ContextSelectionSet<'_>,
|
||||
|
|
|
@ -4,10 +4,10 @@ use crate::parser::types::Field;
|
|||
use crate::resolver_utils::resolve_list;
|
||||
use crate::{
|
||||
registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, OutputType,
|
||||
Positioned, Result, ServerResult, Type, Value,
|
||||
Positioned, Result, ServerResult, Value,
|
||||
};
|
||||
|
||||
impl<T: Type> Type for Vec<T> {
|
||||
impl<T: InputType> InputType for Vec<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Owned(format!("[{}]", T::qualified_type_name()))
|
||||
}
|
||||
|
@ -20,9 +20,7 @@ impl<T: Type> Type for Vec<T> {
|
|||
T::create_type_info(registry);
|
||||
Self::qualified_type_name()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: InputType> InputType for Vec<T> {
|
||||
fn parse(value: Option<Value>) -> InputValueResult<Self> {
|
||||
match value.unwrap_or_default() {
|
||||
Value::List(values) => values
|
||||
|
@ -43,6 +41,19 @@ impl<T: InputType> InputType for Vec<T> {
|
|||
|
||||
#[async_trait::async_trait]
|
||||
impl<T: OutputType> OutputType for Vec<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Owned(format!("[{}]", T::qualified_type_name()))
|
||||
}
|
||||
|
||||
fn qualified_type_name() -> String {
|
||||
format!("[{}]!", T::qualified_type_name())
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
T::create_type_info(registry);
|
||||
Self::qualified_type_name()
|
||||
}
|
||||
|
||||
async fn resolve(
|
||||
&self,
|
||||
ctx: &ContextSelectionSet<'_>,
|
||||
|
|
|
@ -5,10 +5,10 @@ use crate::parser::types::Field;
|
|||
use crate::resolver_utils::resolve_list;
|
||||
use crate::{
|
||||
registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, OutputType,
|
||||
Positioned, ServerResult, Type, Value,
|
||||
Positioned, ServerResult, Value,
|
||||
};
|
||||
|
||||
impl<T: Type> Type for VecDeque<T> {
|
||||
impl<T: InputType> InputType for VecDeque<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Owned(format!("[{}]", T::qualified_type_name()))
|
||||
}
|
||||
|
@ -21,9 +21,7 @@ impl<T: Type> Type for VecDeque<T> {
|
|||
T::create_type_info(registry);
|
||||
Self::qualified_type_name()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: InputType> InputType for VecDeque<T> {
|
||||
fn parse(value: Option<Value>) -> InputValueResult<Self> {
|
||||
match value.unwrap_or_default() {
|
||||
Value::List(values) => values
|
||||
|
@ -47,6 +45,19 @@ impl<T: InputType> InputType for VecDeque<T> {
|
|||
|
||||
#[async_trait::async_trait]
|
||||
impl<T: OutputType> OutputType for VecDeque<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Owned(format!("[{}]", T::qualified_type_name()))
|
||||
}
|
||||
|
||||
fn qualified_type_name() -> String {
|
||||
format!("[{}]!", T::qualified_type_name())
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
T::create_type_info(registry);
|
||||
Self::qualified_type_name()
|
||||
}
|
||||
|
||||
async fn resolve(
|
||||
&self,
|
||||
ctx: &ContextSelectionSet<'_>,
|
||||
|
|
|
@ -3,10 +3,10 @@ use std::borrow::Cow;
|
|||
use crate::parser::types::Field;
|
||||
use crate::{
|
||||
registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, OutputType,
|
||||
Positioned, ServerResult, Type, Value,
|
||||
Positioned, ServerResult, Value,
|
||||
};
|
||||
|
||||
impl<T: Type> Type for Option<T> {
|
||||
impl<T: InputType> InputType for Option<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
T::type_name()
|
||||
}
|
||||
|
@ -19,9 +19,7 @@ impl<T: Type> Type for Option<T> {
|
|||
T::create_type_info(registry);
|
||||
T::type_name().to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: InputType> InputType for Option<T> {
|
||||
fn parse(value: Option<Value>) -> InputValueResult<Self> {
|
||||
match value.unwrap_or_default() {
|
||||
Value::Null => Ok(None),
|
||||
|
@ -41,6 +39,19 @@ impl<T: InputType> InputType for Option<T> {
|
|||
|
||||
#[async_trait::async_trait]
|
||||
impl<T: OutputType + Sync> OutputType for Option<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
T::type_name()
|
||||
}
|
||||
|
||||
fn qualified_type_name() -> String {
|
||||
T::type_name().to_string()
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
T::create_type_info(registry);
|
||||
T::type_name().to_string()
|
||||
}
|
||||
|
||||
async fn resolve(
|
||||
&self,
|
||||
ctx: &ContextSelectionSet<'_>,
|
||||
|
@ -62,7 +73,7 @@ impl<T: OutputType + Sync> OutputType for Option<T> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::Type;
|
||||
use crate::InputType;
|
||||
|
||||
#[test]
|
||||
fn test_optional_type() {
|
||||
|
|
|
@ -2,9 +2,9 @@ use std::borrow::Cow;
|
|||
|
||||
use secrecy::{Secret, Zeroize};
|
||||
|
||||
use crate::{registry, InputType, InputValueError, InputValueResult, Type, Value};
|
||||
use crate::{registry, InputType, InputValueError, InputValueResult, Value};
|
||||
|
||||
impl<T: Type + Zeroize> Type for Secret<T> {
|
||||
impl<T: InputType + Zeroize> InputType for Secret<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
T::type_name()
|
||||
}
|
||||
|
@ -16,9 +16,7 @@ impl<T: Type + Zeroize> Type for Secret<T> {
|
|||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
T::create_type_info(registry)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: InputType + Zeroize> InputType for Secret<T> {
|
||||
fn parse(value: Option<Value>) -> InputValueResult<Self> {
|
||||
T::parse(value)
|
||||
.map(Secret::new)
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::borrow::Cow;
|
|||
use crate::parser::types::Field;
|
||||
use crate::{
|
||||
registry, ContextSelectionSet, InputValueError, InputValueResult, OutputType, Positioned,
|
||||
Scalar, ScalarType, ServerResult, Type, Value,
|
||||
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.
|
||||
|
@ -25,18 +25,16 @@ impl ScalarType for String {
|
|||
}
|
||||
}
|
||||
|
||||
impl Type for str {
|
||||
#[async_trait::async_trait]
|
||||
impl OutputType for str {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Borrowed("String")
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
<String as Type>::create_type_info(registry)
|
||||
<String as OutputType>::create_type_info(registry)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl OutputType for str {
|
||||
async fn resolve(
|
||||
&self,
|
||||
_: &ContextSelectionSet<'_>,
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::parser::types::Field;
|
|||
use crate::registry::{MetaType, Registry};
|
||||
use crate::{
|
||||
from_value, to_value, ContextSelectionSet, InputValueError, InputValueResult, OutputType,
|
||||
Positioned, Scalar, ScalarType, ServerResult, Type, Value,
|
||||
Positioned, Scalar, ScalarType, ServerResult, Value,
|
||||
};
|
||||
|
||||
/// A scalar that can represent any JSON value.
|
||||
|
@ -74,13 +74,14 @@ impl<T: Serialize> From<T> for OutputJson<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> Type for OutputJson<T> {
|
||||
#[async_trait::async_trait]
|
||||
impl<T: Serialize + Send + Sync> OutputType for OutputJson<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Borrowed("Json")
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut Registry) -> String {
|
||||
registry.create_type::<OutputJson<T>, _>(|_| MetaType::Scalar {
|
||||
registry.create_output_type::<OutputJson<T>, _>(|_| MetaType::Scalar {
|
||||
name: Self::type_name().to_string(),
|
||||
description: None,
|
||||
is_valid: |_| true,
|
||||
|
@ -88,10 +89,7 @@ impl<T> Type for OutputJson<T> {
|
|||
specified_by_url: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<T: Serialize + Send + Sync> OutputType for OutputJson<T> {
|
||||
async fn resolve(
|
||||
&self,
|
||||
_ctx: &ContextSelectionSet<'_>,
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::ops::Deref;
|
|||
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
use crate::{registry, InputType, InputValueError, InputValueResult, Type, Value};
|
||||
use crate::{registry, InputType, InputValueError, InputValueResult, Value};
|
||||
|
||||
/// Similar to `Option`, but it has three states, `undefined`, `null` and `x`.
|
||||
///
|
||||
|
@ -174,7 +174,7 @@ impl<T> MaybeUndefined<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Type> Type for MaybeUndefined<T> {
|
||||
impl<T: InputType> InputType for MaybeUndefined<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
T::type_name()
|
||||
}
|
||||
|
@ -187,9 +187,7 @@ impl<T: Type> Type for MaybeUndefined<T> {
|
|||
T::create_type_info(registry);
|
||||
T::type_name().to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: InputType> InputType for MaybeUndefined<T> {
|
||||
fn parse(value: Option<Value>) -> InputValueResult<Self> {
|
||||
match value {
|
||||
None => Ok(MaybeUndefined::Undefined),
|
||||
|
|
|
@ -1,62 +1,19 @@
|
|||
use std::borrow::Cow;
|
||||
use std::pin::Pin;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
|
||||
use crate::futures_util::Stream;
|
||||
use crate::parser::types::Field;
|
||||
use crate::registry::{MetaType, Registry};
|
||||
use crate::{
|
||||
CacheControl, ContainerType, Context, ContextSelectionSet, OutputType, Positioned,
|
||||
ServerResult, SimpleObject, Type, Value,
|
||||
CacheControl, ContainerType, Context, ContextSelectionSet, OutputType, Positioned, Response,
|
||||
ServerResult, SimpleObject, SubscriptionType, Value,
|
||||
};
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct MergedObject<A, B>(pub A, pub B);
|
||||
|
||||
impl<A: Type, B: Type> Type for MergedObject<A, B> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Owned(format!("{}_{}", A::type_name(), B::type_name()))
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut Registry) -> String {
|
||||
registry.create_type::<Self, _>(|registry| {
|
||||
let mut fields = IndexMap::new();
|
||||
let mut cc = CacheControl::default();
|
||||
|
||||
if let MetaType::Object {
|
||||
fields: b_fields,
|
||||
cache_control: b_cc,
|
||||
..
|
||||
} = registry.create_dummy_type::<B>()
|
||||
{
|
||||
fields.extend(b_fields);
|
||||
cc = cc.merge(&b_cc);
|
||||
}
|
||||
|
||||
if let MetaType::Object {
|
||||
fields: a_fields,
|
||||
cache_control: a_cc,
|
||||
..
|
||||
} = registry.create_dummy_type::<A>()
|
||||
{
|
||||
fields.extend(a_fields);
|
||||
cc = cc.merge(&a_cc);
|
||||
}
|
||||
|
||||
MetaType::Object {
|
||||
name: Self::type_name().to_string(),
|
||||
description: None,
|
||||
fields,
|
||||
cache_control: cc,
|
||||
extends: false,
|
||||
keys: None,
|
||||
visible: None,
|
||||
is_subscription: false,
|
||||
rust_typename: std::any::type_name::<Self>(),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<A, B> ContainerType for MergedObject<A, B>
|
||||
where
|
||||
|
@ -83,9 +40,52 @@ where
|
|||
#[async_trait::async_trait]
|
||||
impl<A, B> OutputType for MergedObject<A, B>
|
||||
where
|
||||
A: ContainerType,
|
||||
B: ContainerType,
|
||||
A: OutputType,
|
||||
B: OutputType,
|
||||
{
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Owned(format!("{}_{}", A::type_name(), B::type_name()))
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut Registry) -> String {
|
||||
registry.create_output_type::<Self, _>(|registry| {
|
||||
let mut fields = IndexMap::new();
|
||||
let mut cc = CacheControl::default();
|
||||
|
||||
if let MetaType::Object {
|
||||
fields: b_fields,
|
||||
cache_control: b_cc,
|
||||
..
|
||||
} = registry.create_fake_output_type::<B>()
|
||||
{
|
||||
fields.extend(b_fields);
|
||||
cc = cc.merge(&b_cc);
|
||||
}
|
||||
|
||||
if let MetaType::Object {
|
||||
fields: a_fields,
|
||||
cache_control: a_cc,
|
||||
..
|
||||
} = registry.create_fake_output_type::<A>()
|
||||
{
|
||||
fields.extend(a_fields);
|
||||
cc = cc.merge(&a_cc);
|
||||
}
|
||||
|
||||
MetaType::Object {
|
||||
name: Self::type_name().to_string(),
|
||||
description: None,
|
||||
fields,
|
||||
cache_control: cc,
|
||||
extends: false,
|
||||
keys: None,
|
||||
visible: None,
|
||||
is_subscription: false,
|
||||
rust_typename: std::any::type_name::<Self>(),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async fn resolve(
|
||||
&self,
|
||||
_ctx: &ContextSelectionSet<'_>,
|
||||
|
@ -95,7 +95,91 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<A, B> SubscriptionType for MergedObject<A, B>
|
||||
where
|
||||
A: SubscriptionType,
|
||||
B: SubscriptionType,
|
||||
{
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Owned(format!("{}_{}", A::type_name(), B::type_name()))
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut Registry) -> String {
|
||||
registry.create_subscription_type::<Self, _>(|registry| {
|
||||
let mut fields = IndexMap::new();
|
||||
let mut cc = CacheControl::default();
|
||||
|
||||
if let MetaType::Object {
|
||||
fields: b_fields,
|
||||
cache_control: b_cc,
|
||||
..
|
||||
} = registry.create_fake_subscription_type::<B>()
|
||||
{
|
||||
fields.extend(b_fields);
|
||||
cc = cc.merge(&b_cc);
|
||||
}
|
||||
|
||||
if let MetaType::Object {
|
||||
fields: a_fields,
|
||||
cache_control: a_cc,
|
||||
..
|
||||
} = registry.create_fake_subscription_type::<A>()
|
||||
{
|
||||
fields.extend(a_fields);
|
||||
cc = cc.merge(&a_cc);
|
||||
}
|
||||
|
||||
MetaType::Object {
|
||||
name: Self::type_name().to_string(),
|
||||
description: None,
|
||||
fields,
|
||||
cache_control: cc,
|
||||
extends: false,
|
||||
keys: None,
|
||||
visible: None,
|
||||
is_subscription: false,
|
||||
rust_typename: std::any::type_name::<Self>(),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn create_field_stream<'a>(
|
||||
&'a self,
|
||||
_ctx: &'a Context<'_>,
|
||||
) -> Option<Pin<Box<dyn Stream<Item = Response> + Send + 'a>>> {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[derive(SimpleObject, Default)]
|
||||
#[graphql(internal, dummy)]
|
||||
#[graphql(internal, fake)]
|
||||
pub struct MergedObjectTail;
|
||||
|
||||
impl SubscriptionType for MergedObjectTail {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Borrowed("MergedSubscriptionTail")
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut Registry) -> String {
|
||||
registry.create_subscription_type::<Self, _>(|_| MetaType::Object {
|
||||
name: "MergedSubscriptionTail".to_string(),
|
||||
description: None,
|
||||
fields: Default::default(),
|
||||
cache_control: Default::default(),
|
||||
extends: false,
|
||||
keys: None,
|
||||
visible: None,
|
||||
is_subscription: false,
|
||||
rust_typename: std::any::type_name::<Self>(),
|
||||
})
|
||||
}
|
||||
|
||||
fn create_field_stream<'a>(
|
||||
&'a self,
|
||||
_ctx: &'a Context<'_>,
|
||||
) -> Option<Pin<Box<dyn Stream<Item = Response> + Send + 'a>>> {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::parser::types::Field;
|
|||
use crate::resolver_utils::{resolve_container, ContainerType};
|
||||
use crate::{
|
||||
registry, Any, Context, ContextSelectionSet, ObjectType, OutputType, Positioned, ServerError,
|
||||
ServerResult, SimpleObject, Type, Value,
|
||||
ServerResult, SimpleObject, Value,
|
||||
};
|
||||
|
||||
/// Federation service
|
||||
|
@ -21,74 +21,6 @@ pub(crate) struct QueryRoot<T> {
|
|||
pub(crate) inner: T,
|
||||
}
|
||||
|
||||
impl<T: Type> Type for QueryRoot<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
T::type_name()
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
let root = T::create_type_info(registry);
|
||||
|
||||
if !registry.disable_introspection {
|
||||
let schema_type = __Schema::create_type_info(registry);
|
||||
if let Some(registry::MetaType::Object { fields, .. }) =
|
||||
registry.types.get_mut(T::type_name().as_ref())
|
||||
{
|
||||
fields.insert(
|
||||
"__schema".to_string(),
|
||||
registry::MetaField {
|
||||
name: "__schema".to_string(),
|
||||
description: Some("Access the current type schema of this server."),
|
||||
args: Default::default(),
|
||||
ty: schema_type,
|
||||
deprecation: Default::default(),
|
||||
cache_control: Default::default(),
|
||||
external: false,
|
||||
requires: None,
|
||||
provides: None,
|
||||
visible: None,
|
||||
compute_complexity: None,
|
||||
},
|
||||
);
|
||||
|
||||
fields.insert(
|
||||
"__type".to_string(),
|
||||
registry::MetaField {
|
||||
name: "__type".to_string(),
|
||||
description: Some("Request the type information of a single type."),
|
||||
args: {
|
||||
let mut args = IndexMap::new();
|
||||
args.insert(
|
||||
"name",
|
||||
registry::MetaInputValue {
|
||||
name: "name",
|
||||
description: None,
|
||||
ty: "String!".to_string(),
|
||||
default_value: None,
|
||||
validator: None,
|
||||
visible: None,
|
||||
is_secret: false,
|
||||
},
|
||||
);
|
||||
args
|
||||
},
|
||||
ty: "__Type".to_string(),
|
||||
deprecation: Default::default(),
|
||||
cache_control: Default::default(),
|
||||
external: false,
|
||||
requires: None,
|
||||
provides: None,
|
||||
visible: None,
|
||||
compute_complexity: None,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
root
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<T: ObjectType> ContainerType for QueryRoot<T> {
|
||||
async fn resolve_field(&self, ctx: &Context<'_>) -> ServerResult<Option<Value>> {
|
||||
|
@ -154,6 +86,72 @@ impl<T: ObjectType> ContainerType for QueryRoot<T> {
|
|||
|
||||
#[async_trait::async_trait]
|
||||
impl<T: ObjectType> OutputType for QueryRoot<T> {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
T::type_name()
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
let root = T::create_type_info(registry);
|
||||
|
||||
if !registry.disable_introspection {
|
||||
let schema_type = __Schema::create_type_info(registry);
|
||||
if let Some(registry::MetaType::Object { fields, .. }) =
|
||||
registry.types.get_mut(T::type_name().as_ref())
|
||||
{
|
||||
fields.insert(
|
||||
"__schema".to_string(),
|
||||
registry::MetaField {
|
||||
name: "__schema".to_string(),
|
||||
description: Some("Access the current type schema of this server."),
|
||||
args: Default::default(),
|
||||
ty: schema_type,
|
||||
deprecation: Default::default(),
|
||||
cache_control: Default::default(),
|
||||
external: false,
|
||||
requires: None,
|
||||
provides: None,
|
||||
visible: None,
|
||||
compute_complexity: None,
|
||||
},
|
||||
);
|
||||
|
||||
fields.insert(
|
||||
"__type".to_string(),
|
||||
registry::MetaField {
|
||||
name: "__type".to_string(),
|
||||
description: Some("Request the type information of a single type."),
|
||||
args: {
|
||||
let mut args = IndexMap::new();
|
||||
args.insert(
|
||||
"name",
|
||||
registry::MetaInputValue {
|
||||
name: "name",
|
||||
description: None,
|
||||
ty: "String!".to_string(),
|
||||
default_value: None,
|
||||
validator: None,
|
||||
visible: None,
|
||||
is_secret: false,
|
||||
},
|
||||
);
|
||||
args
|
||||
},
|
||||
ty: "__Type".to_string(),
|
||||
deprecation: Default::default(),
|
||||
cache_control: Default::default(),
|
||||
external: false,
|
||||
requires: None,
|
||||
provides: None,
|
||||
visible: None,
|
||||
compute_complexity: None,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
root
|
||||
}
|
||||
|
||||
async fn resolve(
|
||||
&self,
|
||||
ctx: &ContextSelectionSet<'_>,
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::io::Read;
|
|||
#[cfg(feature = "unblock")]
|
||||
use futures_util::io::AsyncRead;
|
||||
|
||||
use crate::{registry, Context, InputType, InputValueError, InputValueResult, Type, Value};
|
||||
use crate::{registry, Context, InputType, InputValueError, InputValueResult, Value};
|
||||
|
||||
/// A file upload value.
|
||||
pub struct UploadValue {
|
||||
|
@ -100,13 +100,13 @@ impl Upload {
|
|||
}
|
||||
}
|
||||
|
||||
impl Type for Upload {
|
||||
impl InputType for Upload {
|
||||
fn type_name() -> Cow<'static, str> {
|
||||
Cow::Borrowed("Upload")
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String {
|
||||
registry.create_type::<Self, _>(|_| registry::MetaType::Scalar {
|
||||
registry.create_input_type::<Self, _>(|_| registry::MetaType::Scalar {
|
||||
name: Self::type_name().to_string(),
|
||||
description: None,
|
||||
is_valid: |value| matches!(value, Value::String(_)),
|
||||
|
@ -114,9 +114,7 @@ impl Type for Upload {
|
|||
specified_by_url: Some("https://github.com/jaydenseric/graphql-multipart-request-spec"),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl InputType for Upload {
|
||||
fn parse(value: Option<Value>) -> InputValueResult<Self> {
|
||||
const PREFIX: &str = "#__graphql_file__:";
|
||||
let value = value.unwrap_or_default();
|
||||
|
|
|
@ -258,7 +258,7 @@ pub async fn test_generic_subscription() {
|
|||
}
|
||||
|
||||
#[Subscription]
|
||||
impl<T: OutputType + Type> MySubscription<T>
|
||||
impl<T: OutputType> MySubscription<T>
|
||||
where
|
||||
T: Clone + Send + Sync + Unpin,
|
||||
{
|
||||
|
|
|
@ -349,3 +349,60 @@ pub async fn test_box_input_object() {
|
|||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
pub async fn test_both_input_output() {
|
||||
#[derive(SimpleObject, InputObject)]
|
||||
#[graphql(input_name = "MyObjectInput")]
|
||||
#[allow(dead_code)]
|
||||
struct MyObject {
|
||||
#[graphql(default = 10)]
|
||||
a: i32,
|
||||
b: bool,
|
||||
#[graphql(skip)]
|
||||
c: String,
|
||||
}
|
||||
|
||||
struct Query;
|
||||
|
||||
#[Object]
|
||||
impl Query {
|
||||
async fn obj(&self, input: MyObject) -> MyObject {
|
||||
input
|
||||
}
|
||||
}
|
||||
|
||||
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
|
||||
assert_eq!(
|
||||
schema
|
||||
.execute("{ obj(input: {a: 1, b: true}) { a b } }")
|
||||
.await
|
||||
.into_result()
|
||||
.unwrap()
|
||||
.data,
|
||||
value!({
|
||||
"obj": {
|
||||
"a": 1,
|
||||
"b": true,
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
schema
|
||||
.execute("{ obj(input: {b: true}) { a b } }")
|
||||
.await
|
||||
.into_result()
|
||||
.unwrap()
|
||||
.data,
|
||||
value!({
|
||||
"obj": {
|
||||
"a": 10,
|
||||
"b": true,
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
assert_eq!(<MyObject as InputType>::type_name(), "MyObjectInput");
|
||||
assert_eq!(<MyObject as OutputType>::type_name(), "MyObject");
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@ pub async fn test_multiple_interfaces() {
|
|||
}
|
||||
|
||||
let schema = Schema::build(Query, EmptyMutation, EmptySubscription)
|
||||
.register_type::<InterfaceA>() // `InterfaceA` is not directly referenced, so manual registration is required.
|
||||
.register_output_type::<InterfaceA>() // `InterfaceA` is not directly referenced, so manual registration is required.
|
||||
.finish();
|
||||
let query = r#"{
|
||||
myObj {
|
||||
|
@ -209,7 +209,7 @@ pub async fn test_multiple_objects_in_multiple_interfaces() {
|
|||
}
|
||||
|
||||
let schema = Schema::build(Query, EmptyMutation, EmptySubscription)
|
||||
.register_type::<InterfaceB>() // `InterfaceB` is not directly referenced, so manual registration is required.
|
||||
.register_output_type::<InterfaceB>() // `InterfaceB` is not directly referenced, so manual registration is required.
|
||||
.finish();
|
||||
let query = r#"{
|
||||
myObj {
|
||||
|
|
|
@ -229,7 +229,7 @@ pub async fn test_subscription_fragment() {
|
|||
}
|
||||
|
||||
let schema = Schema::build(QueryRoot, EmptyMutation, SubscriptionRoot)
|
||||
.register_type::<MyInterface>()
|
||||
.register_output_type::<MyInterface>()
|
||||
.finish();
|
||||
let mut stream = schema
|
||||
.execute_stream(
|
||||
|
@ -278,7 +278,7 @@ pub async fn test_subscription_fragment2() {
|
|||
}
|
||||
|
||||
let schema = Schema::build(QueryRoot, EmptyMutation, SubscriptionRoot)
|
||||
.register_type::<MyInterface>()
|
||||
.register_output_type::<MyInterface>()
|
||||
.finish();
|
||||
let mut stream = schema
|
||||
.execute_stream(
|
||||
|
|
|
@ -130,7 +130,7 @@ pub async fn test_multiple_unions() {
|
|||
}
|
||||
|
||||
let schema = Schema::build(Query, EmptyMutation, EmptySubscription)
|
||||
.register_type::<UnionA>() // `UnionA` is not directly referenced, so manual registration is required.
|
||||
.register_output_type::<UnionA>() // `UnionA` is not directly referenced, so manual registration is required.
|
||||
.finish();
|
||||
let query = r#"{
|
||||
unionA {
|
||||
|
@ -214,7 +214,7 @@ pub async fn test_multiple_objects_in_multiple_unions() {
|
|||
}
|
||||
|
||||
let schema = Schema::build(Query, EmptyMutation, EmptySubscription)
|
||||
.register_type::<UnionB>() // `UnionB` is not directly referenced, so manual registration is required.
|
||||
.register_output_type::<UnionB>() // `UnionB` is not directly referenced, so manual registration is required.
|
||||
.finish();
|
||||
let query = r#"{
|
||||
myObj {
|
||||
|
|
|
@ -152,8 +152,8 @@ pub async fn test_override_description() {
|
|||
EmptyMutation,
|
||||
EmptySubscription,
|
||||
)
|
||||
.override_description::<Query>("Hehe")
|
||||
.override_description::<DateTime<Utc>>("DT")
|
||||
.override_output_type_description::<Query>("Hehe")
|
||||
.override_output_type_description::<DateTime<Utc>>("DT")
|
||||
.finish();
|
||||
|
||||
assert_eq!(
|
||||
|
|
Loading…
Reference in New Issue