Add support for extending an entity with computed fields (advanced) #180

This commit is contained in:
Sunli 2020-06-19 12:37:52 +08:00
parent 96ca4ade82
commit 362ba90e7d
3 changed files with 46 additions and 16 deletions

View File

@ -130,6 +130,7 @@ pub struct Argument {
pub desc: Option<String>,
pub default: Option<TokenStream>,
pub validator: TokenStream,
pub key: bool, // for entity
}
impl Argument {
@ -138,6 +139,7 @@ impl Argument {
let mut desc = None;
let mut default = None;
let mut validator = quote! { None };
let mut key = false;
for attr in attrs {
match attr.parse_meta()? {
@ -146,6 +148,8 @@ impl Argument {
if let NestedMeta::Meta(Meta::Path(p)) = meta {
if p.is_ident("default") {
default = Some(quote! { Default::default() });
} else if p.is_ident("key") {
key = true;
}
} else if let NestedMeta::Meta(Meta::NameValue(nv)) = meta {
if nv.path.is_ident("name") {
@ -185,6 +189,7 @@ impl Argument {
desc,
default,
validator,
key,
})
}
}

View File

@ -113,29 +113,51 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
let mut use_keys = Vec::new();
let mut keys = Vec::new();
let mut keys_str = String::new();
let mut requires_getter = Vec::new();
let mut one_key = false;
for (ident, ty, args::Argument { name, .. }) in &args {
if args.is_empty() {
return Err(Error::new_spanned(
method,
"Entity need to have at least one key.",
));
} else if args.len() == 1 {
one_key = true;
}
for (ident, ty, args::Argument { name, key, .. }) in &args {
let is_key = one_key || *key;
let name = name
.clone()
.unwrap_or_else(|| ident.ident.to_string().to_camel_case());
if !keys_str.is_empty() {
keys_str.push(' ');
}
keys_str.push_str(&name);
if is_key {
if !keys_str.is_empty() {
keys_str.push(' ');
}
keys_str.push_str(&name);
key_pat.push(quote! {
Some(#ident)
});
key_getter.push(quote! {
params.get(#name).and_then(|value| {
let value: Option<#ty> = #crate_name::InputValueType::parse(Some(value.clone())).ok();
value
})
});
keys.push(name);
use_keys.push(ident);
key_pat.push(quote! {
Some(#ident)
});
key_getter.push(quote! {
params.get(#name).and_then(|value| {
let value: Option<#ty> = #crate_name::InputValueType::parse(Some(value.clone())).ok();
value
})
});
keys.push(name);
use_keys.push(ident);
} else {
// requires
requires_getter.push(quote! {
let #ident: #ty = #crate_name::InputValueType::parse(params.get(#name).cloned()).
map_err(|err| err.into_error(ctx.position(), <#ty as #crate_name::Type>::qualified_type_name()))?;
});
use_keys.push(ident);
}
}
add_keys.push(quote! { registry.add_keys(&<#entity_type as #crate_name::Type>::type_name(), #keys_str); });
create_entity_types.push(
quote! { <#entity_type as #crate_name::Type>::create_type_info(registry); },
@ -163,6 +185,7 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
quote! {
if typename == &<#entity_type as #crate_name::Type>::type_name() {
if let (#(#key_pat),*) = (#(#key_getter),*) {
#(#requires_getter)*
let ctx_obj = ctx.with_selection_set(&ctx.selection_set);
return #crate_name::OutputValueType::resolve(&#do_find, &ctx_obj, ctx.item).await;
}
@ -290,6 +313,7 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
desc,
default,
validator,
..
},
) in args
{

View File

@ -143,6 +143,7 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
desc,
default,
validator,
..
},
) in args
{