feat: add visible macro argument for union type

This commit is contained in:
Miaxos 2021-10-11 12:26:18 +00:00
parent c9c2fc630e
commit a3b7777516
5 changed files with 37 additions and 5 deletions

View File

@ -304,6 +304,8 @@ pub struct UnionItem {
#[darling(default)]
pub flatten: bool,
#[darling(default)]
pub visible: Option<Visible>,
}
#[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 possible_types = Vec::new();
let mut union_values = Vec::new();
let mut get_introspection_typename = Vec::new();
let mut collect_all_fields = Vec::new();
for variant in s {
let enum_name = &variant.ident;
let union_visible = visible_fn(&variant.visible);
let ty = match variant.fields.style {
Style::Tuple if variant.fields.fields.len() == 1 => &variant.fields.fields[0],
Style::Tuple => {
@ -70,6 +72,15 @@ 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(),
#crate_name::registry::MetaUnionValue {
name: <#p as #crate_name::Type>::type_name().into_owned(),
visible: #union_visible,
}
);
});
struct RemoveLifetime;
impl VisitMut for RemoveLifetime {
@ -176,6 +187,11 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
#(#possible_types)*
possible_types
},
union_values: {
let mut union_values = #crate_name::indexmap::IndexMap::new();
#(#union_values)*
union_values
},
visible: #visible,
}
})

View File

@ -831,6 +831,8 @@ pub use async_graphql_derive::Interface;
/// | Attribute | description | Type | Optional |
/// |--------------|------------------------------------------|----------|----------|
/// | 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
///

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

View File

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