Merge pull request #655 from Miaxos/visible

feat: add visible macro argument for union type
This commit is contained in:
Sunli 2021-10-12 09:52:01 +08:00 committed by GitHub
commit 5b5daa65ea
5 changed files with 37 additions and 5 deletions

View File

@ -304,6 +304,8 @@ pub struct UnionItem {
#[darling(default)] #[darling(default)]
pub flatten: bool, pub flatten: bool,
#[darling(default)]
pub visible: Option<Visible>,
} }
#[derive(FromField)] #[derive(FromField)]

View File

@ -33,11 +33,13 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
let mut registry_types = Vec::new(); let mut registry_types = Vec::new();
let mut possible_types = Vec::new(); let mut possible_types = Vec::new();
let mut union_values = Vec::new();
let mut get_introspection_typename = Vec::new(); let mut get_introspection_typename = Vec::new();
let mut collect_all_fields = Vec::new(); let mut collect_all_fields = Vec::new();
for variant in s { for variant in s {
let enum_name = &variant.ident; let enum_name = &variant.ident;
let union_visible = visible_fn(&variant.visible);
let ty = match variant.fields.style { let ty = match variant.fields.style {
Style::Tuple if variant.fields.fields.len() == 1 => &variant.fields.fields[0], Style::Tuple if variant.fields.fields.len() == 1 => &variant.fields.fields[0],
Style::Tuple => { Style::Tuple => {
@ -70,6 +72,15 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
} }
enum_names.push(enum_name); enum_names.push(enum_name);
union_values.push(quote! {
union_values.insert(
<#p as #crate_name::Type>::type_name().into_owned(),
#crate_name::registry::MetaUnionValue {
name: <#p as #crate_name::Type>::type_name().into_owned(),
visible: #union_visible,
}
);
});
struct RemoveLifetime; struct RemoveLifetime;
impl VisitMut for RemoveLifetime { impl VisitMut for RemoveLifetime {
@ -176,6 +187,11 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
#(#possible_types)* #(#possible_types)*
possible_types possible_types
}, },
union_values: {
let mut union_values = #crate_name::indexmap::IndexMap::new();
#(#union_values)*
union_values
},
visible: #visible, visible: #visible,
} }
}) })

View File

@ -831,6 +831,8 @@ pub use async_graphql_derive::Interface;
/// | Attribute | description | Type | Optional | /// | Attribute | description | Type | Optional |
/// |--------------|------------------------------------------|----------|----------| /// |--------------|------------------------------------------|----------|----------|
/// | flatten | Similar to serde (flatten) | boolean | Y | /// | flatten | Similar to serde (flatten) | boolean | Y |
/// | visible | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
/// | visible | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
/// ///
/// # Define a union /// # Define a union
/// ///

View File

@ -133,7 +133,7 @@ impl<'a> __Type<'a> {
} }
} }
async fn possible_types(&self) -> Option<Vec<__Type<'a>>> { async fn possible_types(&self, ctx: &Context<'_>) -> Option<Vec<__Type<'a>>> {
if let TypeDetail::Named(registry::MetaType::Interface { possible_types, .. }) = if let TypeDetail::Named(registry::MetaType::Interface { possible_types, .. }) =
&self.detail &self.detail
{ {
@ -143,13 +143,17 @@ impl<'a> __Type<'a> {
.map(|ty| __Type::new(self.registry, ty)) .map(|ty| __Type::new(self.registry, ty))
.collect(), .collect(),
) )
} else if let TypeDetail::Named(registry::MetaType::Union { possible_types, .. }) = } else if let TypeDetail::Named(registry::MetaType::Union { union_values, .. }) =
&self.detail &self.detail
{ {
Some( Some(
possible_types union_values
.iter() .values()
.map(|ty| __Type::new(self.registry, ty)) .filter(|value| match &value.visible {
Some(f) => f(ctx),
None => true,
})
.map(|ty| __Type::new(self.registry, &ty.name))
.collect(), .collect(),
) )
} else { } else {

View File

@ -174,6 +174,12 @@ pub struct MetaEnumValue {
pub visible: Option<MetaVisibleFn>, pub visible: Option<MetaVisibleFn>,
} }
#[derive(Clone)]
pub struct MetaUnionValue {
pub name: String,
pub visible: Option<MetaVisibleFn>,
}
type MetaVisibleFn = fn(&Context<'_>) -> bool; type MetaVisibleFn = fn(&Context<'_>) -> bool;
#[derive(Clone)] #[derive(Clone)]
@ -205,6 +211,7 @@ pub enum MetaType {
Union { Union {
name: String, name: String,
description: Option<&'static str>, description: Option<&'static str>,
union_values: IndexMap<String, MetaUnionValue>,
possible_types: IndexSet<String>, possible_types: IndexSet<String>,
visible: Option<MetaVisibleFn>, visible: Option<MetaVisibleFn>,
}, },
@ -461,6 +468,7 @@ impl Registry {
MetaType::Union { MetaType::Union {
name: "_Entity".to_string(), name: "_Entity".to_string(),
description: None, description: None,
union_values: Default::default(),
possible_types, possible_types,
visible: None, visible: None,
}, },