Add support flatten attribute for SimpleObject, ComplexObject and Object macros. #533

This commit is contained in:
Sunli 2022-01-18 10:33:07 +08:00
parent c6bb4c026c
commit 3217f7aecd
22 changed files with 646 additions and 288 deletions

View File

@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [3.0.22] 2022-1-11
- Add support `flatten` attribute for `SimpleObject`, `ComplexObject` and `Object` macros. [#533](https://github.com/async-graphql/async-graphql/issues/533)
## [3.0.21] 2022-1-11
- Add `Union` and `Interface` support for trait objects. [#780](https://github.com/async-graphql/async-graphql/issues/780)

View File

@ -265,6 +265,7 @@ pub struct ObjectField {
pub complexity: Option<ComplexityType>,
#[darling(default, multiple)]
pub derived: Vec<DerivedField>,
pub flatten: bool,
}
#[derive(FromMeta, Default, Clone)]
@ -698,6 +699,9 @@ pub struct ComplexObjectField {
pub guard: Option<SpannedValue<String>>,
pub visible: Option<Visible>,
pub complexity: Option<ComplexityType>,
#[darling(multiple)]
pub derived: Vec<DerivedField>,
pub flatten: bool,
}
#[derive(FromMeta, Default)]

View File

@ -33,7 +33,7 @@ pub fn generate(
let mut derived_impls = vec![];
for item in &mut item_impl.items {
if let ImplItem::Method(method) = item {
let method_args: args::ObjectField =
let method_args: args::ComplexObjectField =
parse_graphql_attrs(&method.attrs)?.unwrap_or_default();
for derived in method_args.derived {
@ -116,12 +116,47 @@ pub fn generate(
for item in &mut item_impl.items {
if let ImplItem::Method(method) = item {
let method_args: args::ObjectField =
let method_args: args::ComplexObjectField =
parse_graphql_attrs(&method.attrs)?.unwrap_or_default();
if method_args.skip {
remove_graphql_attrs(&mut method.attrs);
continue;
}
let cfg_attrs = get_cfg_attrs(&method.attrs);
if method_args.flatten {
let ty = match &method.sig.output {
ReturnType::Type(_, ty) => OutputType::parse(ty)?,
ReturnType::Default => {
return Err(Error::new_spanned(
&method.sig.output,
"Flatten resolver must have a return type",
)
.into())
}
};
let ty = ty.value_type();
let ident = &method.sig.ident;
schema_fields.push(quote! {
#crate_name::static_assertions::assert_impl_one!(#ty: #crate_name::ObjectType);
<#ty>::create_type_info(registry);
if let #crate_name::registry::MetaType::Object { fields: obj_fields, .. } =
registry.create_fake_output_type::<#ty>() {
fields.extend(obj_fields);
}
});
resolvers.push(quote! {
#(#cfg_attrs)*
if let ::std::option::Option::Some(value) = #crate_name::ContainerType::resolve_field(&self.#ident().await, ctx).await? {
return ::std::result::Result::Ok(std::option::Option::Some(value));
}
});
remove_graphql_attrs(&mut method.attrs);
continue;
}
let field_name = method_args.name.clone().unwrap_or_else(|| {
object_args
@ -151,7 +186,6 @@ pub fn generate(
}
}
};
let cfg_attrs = get_cfg_attrs(&method.attrs);
let args = extract_input_args(&crate_name, method)?;
let ty = match &method.sig.output {

View File

@ -258,6 +258,41 @@ pub fn generate(
if method.sig.asyncness.is_none() {
return Err(Error::new_spanned(&method, "Must be asynchronous").into());
}
let cfg_attrs = get_cfg_attrs(&method.attrs);
if method_args.flatten {
let ty = match &method.sig.output {
ReturnType::Type(_, ty) => OutputType::parse(ty)?,
ReturnType::Default => {
return Err(Error::new_spanned(
&method.sig.output,
"Flatten resolver must have a return type",
)
.into())
}
};
let ty = ty.value_type();
let ident = &method.sig.ident;
schema_fields.push(quote! {
#crate_name::static_assertions::assert_impl_one!(#ty: #crate_name::ObjectType);
<#ty>::create_type_info(registry);
if let #crate_name::registry::MetaType::Object { fields: obj_fields, .. } =
registry.create_fake_output_type::<#ty>() {
fields.extend(obj_fields);
}
});
resolvers.push(quote! {
#(#cfg_attrs)*
if let ::std::option::Option::Some(value) = #crate_name::ContainerType::resolve_field(&self.#ident().await, ctx).await? {
return ::std::result::Result::Ok(std::option::Option::Some(value));
}
});
remove_graphql_attrs(&mut method.attrs);
continue;
}
let field_name = method_args.name.clone().unwrap_or_else(|| {
object_args
@ -287,7 +322,6 @@ pub fn generate(
}
}
};
let cfg_attrs = get_cfg_attrs(&method.attrs);
let args = extract_input_args(&crate_name, method)?;
let mut schema_args = Vec::new();

View File

@ -153,21 +153,32 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
let visible = visible_fn(&field.visible);
schema_fields.push(quote! {
fields.insert(::std::borrow::ToOwned::to_owned(#field_name), #crate_name::registry::MetaField {
name: ::std::borrow::ToOwned::to_owned(#field_name),
description: #field_desc,
args: ::std::default::Default::default(),
ty: <#ty as #crate_name::OutputType>::create_type_info(registry),
deprecation: #field_deprecation,
cache_control: #cache_control,
external: #external,
provides: #provides,
requires: #requires,
visible: #visible,
compute_complexity: ::std::option::Option::None,
if !field.flatten {
schema_fields.push(quote! {
fields.insert(::std::borrow::ToOwned::to_owned(#field_name), #crate_name::registry::MetaField {
name: ::std::borrow::ToOwned::to_owned(#field_name),
description: #field_desc,
args: ::std::default::Default::default(),
ty: <#ty as #crate_name::OutputType>::create_type_info(registry),
deprecation: #field_deprecation,
cache_control: #cache_control,
external: #external,
provides: #provides,
requires: #requires,
visible: #visible,
compute_complexity: ::std::option::Option::None,
});
});
});
} else {
schema_fields.push(quote! {
#crate_name::static_assertions::assert_impl_one!(#ty: #crate_name::ObjectType);
#ty::create_type_info(registry);
if let #crate_name::registry::MetaType::Object { fields: obj_fields, .. } =
registry.create_fake_output_type::<#ty>() {
fields.extend(obj_fields);
}
});
}
let guard_map_err = quote! {
.map_err(|err| err.into_server_error(ctx.item.pos))
@ -203,27 +214,33 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
false => quote! { #ty },
};
getters.push(
quote! {
if !field.flatten {
getters.push(quote! {
#[inline]
#[allow(missing_docs)]
#vis async fn #ident(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::Result<#ty> {
::std::result::Result::Ok(#block)
}
}
);
});
resolvers.push(quote! {
if ctx.item.node.name.node == #field_name {
let f = async move {
#guard
self.#ident(ctx).await.map_err(|err| err.into_server_error(ctx.item.pos))
};
let obj = f.await.map_err(|err| ctx.set_error_path(err))?;
let ctx_obj = ctx.with_selection_set(&ctx.item.node.selection_set);
return #crate_name::OutputType::resolve(&obj, &ctx_obj, ctx.item).await.map(::std::option::Option::Some);
}
});
resolvers.push(quote! {
if ctx.item.node.name.node == #field_name {
let f = async move {
#guard
self.#ident(ctx).await.map_err(|err| err.into_server_error(ctx.item.pos))
};
let obj = f.await.map_err(|err| ctx.set_error_path(err))?;
let ctx_obj = ctx.with_selection_set(&ctx.item.node.selection_set);
return #crate_name::OutputType::resolve(&obj, &ctx_obj, ctx.item).await.map(::std::option::Option::Some);
}
});
} else {
resolvers.push(quote! {
if let ::std::option::Option::Some(value) = #crate_name::ContainerType::resolve_field(&self.#ident, ctx).await? {
return ::std::result::Result::Ok(std::option::Option::Some(value));
}
});
}
}
if !object_args.fake && resolvers.is_empty() {

View File

@ -10,45 +10,46 @@ some simple fields, and use the `ComplexObject` macro to define some other field
# Macro attributes
| Attribute | description | Type | Optional |
|---------------|---------------------------|----------|----------|
| name | Object name | string | Y |
| rename_fields | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string | Y |
| rename_args | Rename all the arguments according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string | Y |
| Attribute | description | Type | Optional |
|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------|----------|
| name | Object name | string | Y |
| rename_fields | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE". | string | Y |
| rename_args | Rename all the arguments according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE". | string | Y |
# Field attributes
| Attribute | description | Type | Optional |
|---------------|---------------------------|----------|----------|
| skip | Skip this field | bool | Y |
| name | Field name | string | Y |
| desc | Field description | string | Y |
| deprecation | Field deprecated | bool | Y |
| deprecation | Field deprecation reason | string | Y |
| cache_control | Field cache control | [`CacheControl`](struct.CacheControl.html) | Y |
| external | Mark a field as owned by another service. This allows service A to use fields from service B while also knowing at runtime the types of that field. | bool | Y |
| provides | Annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway. | string | Y |
| requires | Annotate the required input fieldset from a base type for a resolver. It is used to develop a query plan where the required fields may not be needed by the client, but the service may need additional information from other services. | string | Y |
| guard | Field of guard *[See also the Book](https://async-graphql.github.io/async-graphql/en/field_guard.html)* | string | 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 |
| complexity | Custom field complexity. *[See also the Book](https://async-graphql.github.io/async-graphql/en/depth_and_complexity.html).* | bool | Y |
| complexity | Custom field complexity. | string | Y |
| derived | Generate derived fields *[See also the Book](https://async-graphql.github.io/async-graphql/en/derived_fields.html).* | object | Y |
| Attribute | description | Type | Optional |
|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------|----------|
| skip | Skip this field | bool | Y |
| name | Field name | string | Y |
| desc | Field description | string | Y |
| deprecation | Field deprecated | bool | Y |
| deprecation | Field deprecation reason | string | Y |
| cache_control | Field cache control | [`CacheControl`](struct.CacheControl.html) | Y |
| external | Mark a field as owned by another service. This allows service A to use fields from service B while also knowing at runtime the types of that field. | bool | Y |
| provides | Annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway. | string | Y |
| requires | Annotate the required input fieldset from a base type for a resolver. It is used to develop a query plan where the required fields may not be needed by the client, but the service may need additional information from other services. | string | Y |
| guard | Field of guard *[See also the Book](https://async-graphql.github.io/async-graphql/en/field_guard.html)* | string | 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 |
| complexity | Custom field complexity. *[See also the Book](https://async-graphql.github.io/async-graphql/en/depth_and_complexity.html).* | bool | Y |
| complexity | Custom field complexity. | string | Y |
| derived | Generate derived fields *[See also the Book](https://async-graphql.github.io/async-graphql/en/derived_fields.html).* | object | Y |
| flatten | Similar to serde (flatten) | boolean | Y |
# Field argument attributes
| Attribute | description | Type | Optional |
|--------------|------------------------------------------|------------ |----------|
| name | Argument name | string | Y |
| desc | Argument description | string | Y |
| default | Use `Default::default` for default value | none | Y |
| default | Argument default value | literal | Y |
| default_with | Expression to generate default value | code string | Y |
| validator | Input value validator *[See also the Book](https://async-graphql.github.io/async-graphql/en/input_value_validators.html)* | object | 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 |
| secret | Mark this field as a secret, it will not output the actual value in the log. | bool | Y |
| Attribute | description | Type | Optional |
|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------|-------------|----------|
| name | Argument name | string | Y |
| desc | Argument description | string | Y |
| default | Use `Default::default` for default value | none | Y |
| default | Argument default value | literal | Y |
| default_with | Expression to generate default value | code string | Y |
| validator | Input value validator *[See also the Book](https://async-graphql.github.io/async-graphql/en/input_value_validators.html)* | object | 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 |
| secret | Mark this field as a secret, it will not output the actual value in the log. | bool | Y |
# Examples

View File

@ -4,28 +4,28 @@ Define a directive for query.
# Macro attributes
| Attribute | description | Type | Optional |
|---------------|---------------------------|----------|----------|
| name | Object name | string | 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 |
| repeatable | It means that the directive can be used multiple times in the same location. | bool | Y |
| rename_args | Rename all the arguments according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string | Y |
| locations | Specify the location where the directive is available, multiples are allowed. The possible values is "field", ... | string | N |
| Attribute | description | Type | Optional |
|-------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------|----------|
| name | Object name | string | 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 |
| repeatable | It means that the directive can be used multiple times in the same location. | bool | Y |
| rename_args | Rename all the arguments according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE". | string | Y |
| locations | Specify the location where the directive is available, multiples are allowed. The possible values is "field", ... | string | N |
# Directive attributes
| Attribute | description | Type | Optional |
|--------------|------------------------------------------|------------ |----------|
| name | Argument name | string | Y |
| desc | Argument description | string | Y |
| default | Use `Default::default` for default value | none | Y |
| default | Argument default value | literal | Y |
| default_with | Expression to generate default value | code string | Y |
| validator | Input value validator *[See also the Book](https://async-graphql.github.io/async-graphql/en/input_value_validators.html)* | object | 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 |
| secret | Mark this field as a secret, it will not output the actual value in the log. | bool | Y |
| Attribute | description | Type | Optional |
|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------|-------------|----------|
| name | Argument name | string | Y |
| desc | Argument description | string | Y |
| default | Use `Default::default` for default value | none | Y |
| default | Argument default value | literal | Y |
| default_with | Expression to generate default value | code string | Y |
| validator | Input value validator *[See also the Book](https://async-graphql.github.io/async-graphql/en/input_value_validators.html)* | object | 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 |
| secret | Mark this field as a secret, it will not output the actual value in the log. | bool | Y |
# Examples

View File

@ -4,23 +4,23 @@ Define a GraphQL enum
# Macro attributes
| Attribute | description | Type | Optional |
|--------------|---------------------------|----------|----------|
| name | Enum name | string | Y |
| rename_items | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string | Y |
| remote | Derive a remote enum | string | 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 |
| Attribute | description | Type | Optional |
|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------|----------|
| name | Enum name | string | Y |
| rename_items | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE". | string | Y |
| remote | Derive a remote enum | string | 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 |
# Item attributes
| Attribute | description | Type | Optional |
|-------------|---------------------------|----------|----------|
| name | Item name | string | Y |
| deprecation | Item deprecated | bool | Y |
| deprecation | Item deprecation reason | string | 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 |
| Attribute | description | Type | Optional |
|-------------|-------------------------------------------------------------------------------------------------------------------------------------------------|--------|----------|
| name | Item name | string | Y |
| deprecation | Item deprecated | bool | Y |
| deprecation | Item deprecation reason | string | 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 |
# Examples

View File

@ -4,27 +4,27 @@ Define a GraphQL input object
# Macro attributes
| Attribute | description | Type | Optional |
|---------------|---------------------------|----------|----------|
| name | Object name | string | Y |
| rename_fields | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string | 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 |
| Attribute | description | Type | Optional |
|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------|----------|
| name | Object name | string | Y |
| rename_fields | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE". | string | 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 |
# Field attributes
| Attribute | description | Type | Optional |
|--------------|------------------------------------------|-------------|----------|
| name | Field name | string | Y |
| default | Use `Default::default` for default value | none | Y |
| default | Argument default value | literal | Y |
| default_with | Expression to generate default value | code string | Y |
| validator | Input value validator *[See also the Book](https://async-graphql.github.io/async-graphql/en/input_value_validators.html)* | object | Y |
| flatten | Similar to serde (flatten) | boolean | Y |
| skip | Skip this field, use `Default::default` to get a default value for this field. | bool | 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 |
| secret | Mark this field as a secret, it will not output the actual value in the log. | bool | Y |
| Attribute | description | Type | Optional |
|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------|-------------|----------|
| name | Field name | string | Y |
| default | Use `Default::default` for default value | none | Y |
| default | Argument default value | literal | Y |
| default_with | Expression to generate default value | code string | Y |
| validator | Input value validator *[See also the Book](https://async-graphql.github.io/async-graphql/en/input_value_validators.html)* | object | Y |
| flatten | Similar to serde (flatten) | boolean | Y |
| skip | Skip this field, use `Default::default` to get a default value for this field. | bool | 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 |
| secret | Mark this field as a secret, it will not output the actual value in the log. | bool | Y |
# Examples

View File

@ -4,46 +4,46 @@ Define a GraphQL interface
# Macro attributes
| Attribute | description | Type | Optional |
|---------------|---------------------------|----------|----------|
| name | Object name | string | Y |
| rename_fields | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string | Y |
| rename_args | Rename all the arguments according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string | Y |
| field | Fields of this Interface | InterfaceField | N |
| extends | Add fields to an entity that's defined in another service | bool | 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 |
| Attribute | description | Type | Optional |
|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------|----------|
| name | Object name | string | Y |
| rename_fields | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE". | string | Y |
| rename_args | Rename all the arguments according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE". | string | Y |
| field | Fields of this Interface | InterfaceField | N |
| extends | Add fields to an entity that's defined in another service | bool | 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 |
# Field attributes
| Attribute | description | Type | Optional |
|-------------|---------------------------|----------|----------|
| name | Field name | string | N |
| type | Field type | string | N |
| method | Rust resolver method name. If specified, `name` will not be camelCased in schema definition | string | Y |
| desc | Field description | string | Y |
| deprecation | Field deprecated | bool | Y |
| deprecation | Field deprecation reason | string | Y |
| arg | Field arguments | InterfaceFieldArgument | Y |
| external | Mark a field as owned by another service. This allows service A to use fields from service B while also knowing at runtime the types of that field. | bool | Y |
| provides | Annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway. | string | Y |
| requires | Annotate the required input fieldset from a base type for a resolver. It is used to develop a query plan where the required fields may not be needed by the client, but the service may need additional information from other services. | string | 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 |
| Attribute | description | Type | Optional |
|-------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------|----------|
| name | Field name | string | N |
| type | Field type | string | N |
| method | Rust resolver method name. If specified, `name` will not be camelCased in schema definition | string | Y |
| desc | Field description | string | Y |
| deprecation | Field deprecated | bool | Y |
| deprecation | Field deprecation reason | string | Y |
| arg | Field arguments | InterfaceFieldArgument | Y |
| external | Mark a field as owned by another service. This allows service A to use fields from service B while also knowing at runtime the types of that field. | bool | Y |
| provides | Annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway. | string | Y |
| requires | Annotate the required input fieldset from a base type for a resolver. It is used to develop a query plan where the required fields may not be needed by the client, but the service may need additional information from other services. | string | 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 |
# Field argument attributes
| Attribute | description | Type | Optional |
|--------------|------------------------------------------|-------------|----------|
| name | Argument name | string | N |
| type | Argument type | string | N |
| desc | Argument description | string | Y |
| default | Use `Default::default` for default value | none | Y |
| default | Argument default value | literal | Y |
| default_with | Expression to generate default value | code string | 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 |
| secret | Mark this field as a secret, it will not output the actual value in the log. | bool | Y |
| Attribute | description | Type | Optional |
|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------|-------------|----------|
| name | Argument name | string | N |
| type | Argument type | string | N |
| desc | Argument description | string | Y |
| default | Use `Default::default` for default value | none | Y |
| default | Argument default value | literal | Y |
| default_with | Expression to generate default value | code string | 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 |
| secret | Mark this field as a secret, it will not output the actual value in the log. | bool | Y |
# Define an interface

View File

@ -4,14 +4,14 @@ Define a merged object with multiple object types.
# Macro attributes
| Attribute | description | Type | Optional |
|---------------|---------------------------|----------|----------|
| name | Object name | string | Y |
| cache_control | Object cache control | [`CacheControl`](struct.CacheControl.html) | Y |
| extends | Add fields to an entity that's defined in another service | bool | 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 |
| serial | Resolve each field sequentially. | bool | Y |
| Attribute | description | Type | Optional |
|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------|----------|
| name | Object name | string | Y |
| cache_control | Object cache control | [`CacheControl`](struct.CacheControl.html) | Y |
| extends | Add fields to an entity that's defined in another service | bool | 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 |
| serial | Resolve each field sequentially. | bool | Y |
# Examples

View File

@ -4,12 +4,12 @@ Define a merged subscription with multiple subscription types.
# Macro attributes
| Attribute | description | Type | Optional |
|---------------|---------------------------|----------|----------|
| name | Object name | string | Y |
| extends | Add fields to an entity that's defined in another service | bool | 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 |
| Attribute | description | Type | Optional |
|-----------|-------------------------------------------------------------------------------------------------------------------------------------------------|--------|----------|
| name | Object name | string | Y |
| extends | Add fields to an entity that's defined in another service | bool | 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 |
# Examples

View File

@ -4,13 +4,13 @@ It also implements `From<InnerType>` and `Into<InnerType>`.
# Macro attributes
| Attribute | description | Type | Optional |
|-------------|---------------------------|----------|----------|
| name | If this attribute is provided then define a new scalar, otherwise it is just a transparent proxy for the internal scalar. | string | Y |
| name | If this attribute is provided then define a new scalar, otherwise it is just a transparent proxy for the internal scalar. | bool | Y |
| visible(Only valid for new scalars) | 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(Only valid for new scalars) | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
| specified_by_url(Only valid for new scalars) | Provide a specification URL for this scalar type, it must link to a human-readable specification of the data format, serialization and coercion rules for this scalar. | string | Y |
| Attribute | description | Type | Optional |
|----------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------|----------|
| name | If this attribute is provided then define a new scalar, otherwise it is just a transparent proxy for the internal scalar. | string | Y |
| name | If this attribute is provided then define a new scalar, otherwise it is just a transparent proxy for the internal scalar. | bool | Y |
| visible(Only valid for new scalars) | 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(Only valid for new scalars) | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
| specified_by_url(Only valid for new scalars) | Provide a specification URL for this scalar type, it must link to a human-readable specification of the data format, serialization and coercion rules for this scalar. | string | Y |
# Examples

View File

@ -6,60 +6,61 @@ All methods are converted to camelCase.
# Macro attributes
| Attribute | description | Type | Optional |
|---------------|---------------------------|----------|----------|
| name | Object name | string | Y |
| rename_fields | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string | Y |
| rename_args | Rename all the arguments according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string | Y |
| cache_control | Object cache control | [`CacheControl`](struct.CacheControl.html) | Y |
| extends | Add fields to an entity that's defined in another service | bool | Y |
| use_type_description | Specifies that the description of the type is on the type declaration. [`Description`]()(derive.Description.html) | bool | 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 |
| serial | Resolve each field sequentially. | bool | Y |
| Attribute | description | Type | Optional |
|----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------|----------|
| name | Object name | string | Y |
| rename_fields | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE". | string | Y |
| rename_args | Rename all the arguments according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE". | string | Y |
| cache_control | Object cache control | [`CacheControl`](struct.CacheControl.html) | Y |
| extends | Add fields to an entity that's defined in another service | bool | Y |
| use_type_description | Specifies that the description of the type is on the type declaration. [`Description`]()(derive.Description.html) | bool | 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 |
| serial | Resolve each field sequentially. | bool | Y |
# Field attributes
| Attribute | description | Type | Optional |
|---------------|---------------------------|----------|----------|
| skip | Skip this field | bool | Y |
| name | Field name | string | Y |
| desc | Field description | string | Y |
| deprecation | Field deprecated | bool | Y |
| deprecation | Field deprecation reason | string | Y |
| cache_control | Field cache control | [`CacheControl`](struct.CacheControl.html) | Y |
| external | Mark a field as owned by another service. This allows service A to use fields from service B while also knowing at runtime the types of that field. | bool | Y |
| provides | Annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway. | string | Y |
| requires | Annotate the required input fieldset from a base type for a resolver. It is used to develop a query plan where the required fields may not be needed by the client, but the service may need additional information from other services. | string | Y |
| guard | Field of guard *[See also the Book](https://async-graphql.github.io/async-graphql/en/field_guard.html)* | string | 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 |
| complexity | Custom field complexity. *[See also the Book](https://async-graphql.github.io/async-graphql/en/depth_and_complexity.html).* | bool | Y |
| complexity | Custom field complexity. | string | Y |
| derived | Generate derived fields *[See also the Book](https://async-graphql.github.io/async-graphql/en/derived_fields.html).* | object | Y |
| Attribute | description | Type | Optional |
|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------|----------|
| skip | Skip this field | bool | Y |
| name | Field name | string | Y |
| desc | Field description | string | Y |
| deprecation | Field deprecated | bool | Y |
| deprecation | Field deprecation reason | string | Y |
| cache_control | Field cache control | [`CacheControl`](struct.CacheControl.html) | Y |
| external | Mark a field as owned by another service. This allows service A to use fields from service B while also knowing at runtime the types of that field. | bool | Y |
| provides | Annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway. | string | Y |
| requires | Annotate the required input fieldset from a base type for a resolver. It is used to develop a query plan where the required fields may not be needed by the client, but the service may need additional information from other services. | string | Y |
| guard | Field of guard *[See also the Book](https://async-graphql.github.io/async-graphql/en/field_guard.html)* | string | 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 |
| complexity | Custom field complexity. *[See also the Book](https://async-graphql.github.io/async-graphql/en/depth_and_complexity.html).* | bool | Y |
| complexity | Custom field complexity. | string | Y |
| derived | Generate derived fields *[See also the Book](https://async-graphql.github.io/async-graphql/en/derived_fields.html).* | object | Y |
| flatten | Similar to serde (flatten) | boolean | Y |
# Field argument attributes
| Attribute | description | Type | Optional |
|--------------|------------------------------------------|------------ |----------|
| name | Argument name | string | Y |
| desc | Argument description | string | Y |
| default | Use `Default::default` for default value | none | Y |
| default | Argument default value | literal | Y |
| default_with | Expression to generate default value | code string | Y |
| validator | Input value validator *[See also the Book](https://async-graphql.github.io/async-graphql/en/input_value_validators.html)* | object | 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 |
| secret | Mark this field as a secret, it will not output the actual value in the log. | bool | Y |
| key | Is entity key(for Federation) | bool | Y |
| Attribute | description | Type | Optional |
|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------|-------------|----------|
| name | Argument name | string | Y |
| desc | Argument description | string | Y |
| default | Use `Default::default` for default value | none | Y |
| default | Argument default value | literal | Y |
| default_with | Expression to generate default value | code string | Y |
| validator | Input value validator *[See also the Book](https://async-graphql.github.io/async-graphql/en/input_value_validators.html)* | object | 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 |
| secret | Mark this field as a secret, it will not output the actual value in the log. | bool | Y |
| key | Is entity key(for Federation) | bool | Y |
# Derived argument attributes
| Attribute | description | Type | Optional |
|--------------|------------------------------------------|------------ |----------|
| name | Generated derived field name | string | N |
| into | Type to derived an into | string | Y |
| with | Function to apply to manage advanced use cases | string| Y |
| Attribute | description | Type | Optional |
|-----------|------------------------------------------------|--------|----------|
| name | Generated derived field name | string | N |
| into | Type to derived an into | string | Y |
| with | Function to apply to manage advanced use cases | string | Y |
# Valid field return types

View File

@ -2,7 +2,7 @@ Define a Scalar
# Macro attributes
| Attribute | description | Type | Optional |
|-------------|---------------------------|----------|----------|
| name | Scalar name | string | Y |
| specified_by_url | Provide a specification URL for this scalar type, it must link to a human-readable specification of the data format, serialization and coercion rules for this scalar. | string | Y |
| Attribute | description | Type | Optional |
|------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------|----------|
| name | Scalar name | string | Y |
| specified_by_url | Provide a specification URL for this scalar type, it must link to a human-readable specification of the data format, serialization and coercion rules for this scalar. | string | Y |

View File

@ -6,43 +6,44 @@ Similar to `Object`, but defined on a structure that automatically generates get
# Macro attributes
| Attribute | description | Type | Optional |
|---------------|---------------------------|----------|----------|
| name | Object name | string | Y |
| rename_fields | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string | Y |
| cache_control | Object cache control | [`CacheControl`](struct.CacheControl.html) | Y |
| extends | Add fields to an entity that's defined in another service | bool | 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 |
| concretes | Specify how the concrete type of the generic SimpleObject should be implemented. *[See also the Book](https://async-graphql.github.io/async-graphql/en/define_simple_object.html#generic-simpleobjects) | ConcreteType | Y |
| serial | Resolve each field sequentially. | bool | Y |
| Attribute | description | Type | Optional |
|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------|----------|
| name | Object name | string | Y |
| rename_fields | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE". | string | Y |
| cache_control | Object cache control | [`CacheControl`](struct.CacheControl.html) | Y |
| extends | Add fields to an entity that's defined in another service | bool | 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 |
| concretes | Specify how the concrete type of the generic SimpleObject should be implemented. *[See also the Book](https://async-graphql.github.io/async-graphql/en/define_simple_object.html#generic-simpleobjects) | ConcreteType | Y |
| serial | Resolve each field sequentially. | bool | Y |
# Field attributes
| Attribute | description | Type | Optional |
|---------------|---------------------------|----------|----------|
| skip | Skip this field | bool | Y |
| name | Field name | string | Y |
| deprecation | Field deprecated | bool | Y |
| deprecation | Field deprecation reason | string | Y |
| derived | Generate derived fields *[See also the Book](https://async-graphql.github.io/async-graphql/en/derived_fields.html).* | object | Y |
| owned | Field resolver return a ownedship value | bool | Y |
| cache_control | Field cache control | [`CacheControl`](struct.CacheControl.html) | Y |
| external | Mark a field as owned by another service. This allows service A to use fields from service B while also knowing at runtime the types of that field. | bool | Y |
| provides | Annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway. | string | Y |
| requires | Annotate the required input fieldset from a base type for a resolver. It is used to develop a query plan where the required fields may not be needed by the client, but the service may need additional information from other services. | string | Y |
| guard | Field of guard *[See also the Book](https://async-graphql.github.io/async-graphql/en/field_guard.html)* | string | 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 |
| Attribute | description | Type | Optional |
|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------|----------|
| skip | Skip this field | bool | Y |
| name | Field name | string | Y |
| deprecation | Field deprecated | bool | Y |
| deprecation | Field deprecation reason | string | Y |
| derived | Generate derived fields *[See also the Book](https://async-graphql.github.io/async-graphql/en/derived_fields.html).* | object | Y |
| owned | Field resolver return a ownedship value | bool | Y |
| cache_control | Field cache control | [`CacheControl`](struct.CacheControl.html) | Y |
| external | Mark a field as owned by another service. This allows service A to use fields from service B while also knowing at runtime the types of that field. | bool | Y |
| provides | Annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway. | string | Y |
| requires | Annotate the required input fieldset from a base type for a resolver. It is used to develop a query plan where the required fields may not be needed by the client, but the service may need additional information from other services. | string | Y |
| guard | Field of guard *[See also the Book](https://async-graphql.github.io/async-graphql/en/field_guard.html)* | string | 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 |
| flatten | Similar to serde (flatten) | boolean | Y |
# Derived attributes
| Attribute | description | Type | Optional |
|--------------|------------------------------------------|------------ |----------|
| name | Generated derived field name | string | N |
| into | Type to derived an into | string | Y |
| owned | Field resolver return a ownedship value | bool | Y |
| with | Function to apply to manage advanced use cases | string| Y |
| Attribute | description | Type | Optional |
|-----------|------------------------------------------------|--------|----------|
| name | Generated derived field name | string | N |
| into | Type to derived an into | string | Y |
| owned | Field resolver return a ownedship value | bool | Y |
| with | Function to apply to manage advanced use cases | string | Y |
# Examples

View File

@ -9,42 +9,42 @@ The filter function should be synchronous.
# Macro attributes
| Attribute | description | Type | Optional |
|---------------|---------------------------|----------|----------|
| name | Object name | string | Y |
| rename_fields | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string | Y |
| rename_args | Rename all the arguments according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE".| string | Y |
| extends | Add fields to an entity that's defined in another service | bool | 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 |
| use_type_description | Specifies that the description of the type is on the type declaration. [`Description`]()(derive.Description.html) | bool | Y |
| Attribute | description | Type | Optional |
|----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------|----------|
| name | Object name | string | Y |
| rename_fields | Rename all the fields according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE". | string | Y |
| rename_args | Rename all the arguments according to the given case convention. The possible values are "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE". | string | Y |
| extends | Add fields to an entity that's defined in another service | bool | 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 |
| use_type_description | Specifies that the description of the type is on the type declaration. [`Description`]()(derive.Description.html) | bool | Y |
# Field attributes
| Attribute | description | Type | Optional |
|-------------|---------------------------|----------|----------|
| name | Field name | string | Y |
| deprecation | Field deprecated | bool | Y |
| deprecation | Field deprecation reason | string | Y |
| guard | Field of guard *[See also the Book](https://async-graphql.github.io/async-graphql/en/field_guard.html)* | string | 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 |
| complexity | Custom field complexity. *[See also the Book](https://async-graphql.github.io/async-graphql/en/depth_and_complexity.html).* | bool | Y |
| complexity | Custom field complexity. | string | Y |
| secret | Mark this field as a secret, it will not output the actual value in the log. | bool | Y |
| Attribute | description | Type | Optional |
|-------------|-------------------------------------------------------------------------------------------------------------------------------------------------|--------|----------|
| name | Field name | string | Y |
| deprecation | Field deprecated | bool | Y |
| deprecation | Field deprecation reason | string | Y |
| guard | Field of guard *[See also the Book](https://async-graphql.github.io/async-graphql/en/field_guard.html)* | string | 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 |
| complexity | Custom field complexity. *[See also the Book](https://async-graphql.github.io/async-graphql/en/depth_and_complexity.html).* | bool | Y |
| complexity | Custom field complexity. | string | Y |
| secret | Mark this field as a secret, it will not output the actual value in the log. | bool | Y |
# Field argument attributes
| Attribute | description | Type | Optional |
|--------------|------------------------------------------|------------ |----------|
| name | Argument name | string | Y |
| desc | Argument description | string | Y |
| default | Use `Default::default` for default value | none | Y |
| default | Argument default value | literal | Y |
| default_with | Expression to generate default value | code string | Y |
| validator | Input value validator *[See also the Book](https://async-graphql.github.io/async-graphql/en/input_value_validators.html)* | object | 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 |
| Attribute | description | Type | Optional |
|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------|-------------|----------|
| name | Argument name | string | Y |
| desc | Argument description | string | Y |
| default | Use `Default::default` for default value | none | Y |
| default | Argument default value | literal | Y |
| default_with | Expression to generate default value | code string | Y |
| validator | Input value validator *[See also the Book](https://async-graphql.github.io/async-graphql/en/input_value_validators.html)* | object | 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 |
# Examples

View File

@ -4,11 +4,11 @@ Define a GraphQL union
# Macro attributes
| Attribute | description | Type | Optional |
|-------------|---------------------------|----------|----------|
| name | Object name | string | 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 |
| Attribute | description | Type | Optional |
|-----------|-------------------------------------------------------------------------------------------------------------------------------------------------|--------|----------|
| name | Object name | string | 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 |
# Item attributes

View File

@ -8,7 +8,8 @@ use indexmap::IndexMap;
use crate::extensions::ResolveInfo;
use crate::parser::types::Selection;
use crate::{
Context, ContextBase, ContextSelectionSet, Name, OutputType, ServerError, ServerResult, Value,
Context, ContextBase, ContextSelectionSet, Error, Name, OutputType, ServerError, ServerResult,
Value,
};
/// Represents a GraphQL container object.
@ -84,6 +85,23 @@ impl<T: ContainerType + ?Sized> ContainerType for Box<T> {
}
}
#[async_trait::async_trait]
impl<T: ContainerType, E: Into<Error> + Send + Sync + Clone> ContainerType for Result<T, E> {
async fn resolve_field(&self, ctx: &Context<'_>) -> ServerResult<Option<Value>> {
match self {
Ok(value) => T::resolve_field(value, ctx).await,
Err(err) => Err(ctx.set_error_path(err.clone().into().into_server_error(ctx.item.pos))),
}
}
async fn find_entity(&self, ctx: &Context<'_>, params: &Value) -> ServerResult<Option<Value>> {
match self {
Ok(value) => T::find_entity(value, ctx, params).await,
Err(err) => Err(ctx.set_error_path(err.clone().into().into_server_error(ctx.item.pos))),
}
}
}
/// Resolve an container by executing each of the fields concurrently.
pub async fn resolve_container<'a, T: ContainerType + ?Sized>(
ctx: &ContextSelectionSet<'a>,

View File

@ -300,3 +300,131 @@ pub async fn test_complex_object_with_generic_concrete_type() {
})
);
}
#[tokio::test]
async fn test_flatten() {
#[derive(SimpleObject)]
struct A {
a: i32,
b: i32,
}
#[derive(SimpleObject)]
#[graphql(complex)]
struct B {
#[graphql(skip)]
a: A,
c: i32,
}
#[ComplexObject]
impl B {
#[graphql(flatten)]
async fn a(&self) -> &A {
&self.a
}
}
struct Query;
#[Object]
impl Query {
async fn obj(&self) -> B {
B {
a: A { a: 100, b: 200 },
c: 300,
}
}
}
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
let query = "{ __type(name: \"B\") { fields { name } } }";
assert_eq!(
schema.execute(query).await.data,
value!({
"__type": {
"fields": [
{"name": "c"},
{"name": "a"},
{"name": "b"}
]
}
})
);
let query = "{ obj { a b c } }";
assert_eq!(
schema.execute(query).await.data,
value!({
"obj": {
"a": 100,
"b": 200,
"c": 300,
}
})
);
}
#[tokio::test]
async fn test_flatten_with_result() {
#[derive(SimpleObject)]
struct A {
a: i32,
b: i32,
}
#[derive(SimpleObject)]
#[graphql(complex)]
struct B {
#[graphql(skip)]
a: A,
c: i32,
}
#[ComplexObject]
impl B {
#[graphql(flatten)]
async fn a(&self) -> FieldResult<&A> {
Ok(&self.a)
}
}
struct Query;
#[Object]
impl Query {
async fn obj(&self) -> B {
B {
a: A { a: 100, b: 200 },
c: 300,
}
}
}
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
let query = "{ __type(name: \"B\") { fields { name } } }";
assert_eq!(
schema.execute(query).await.data,
value!({
"__type": {
"fields": [
{"name": "c"},
{"name": "a"},
{"name": "b"}
]
}
})
);
let query = "{ obj { a b c } }";
assert_eq!(
schema.execute(query).await.data,
value!({
"obj": {
"a": 100,
"b": 200,
"c": 300,
}
})
);
}

60
tests/object.rs Normal file
View File

@ -0,0 +1,60 @@
use async_graphql::*;
#[tokio::test]
async fn test_flatten() {
#[derive(SimpleObject)]
struct A {
a: i32,
b: i32,
}
struct B;
#[Object]
impl B {
#[graphql(flatten)]
async fn a(&self) -> A {
A { a: 100, b: 200 }
}
async fn c(&self) -> i32 {
300
}
}
struct Query;
#[Object]
impl Query {
async fn obj(&self) -> B {
B
}
}
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
let query = "{ __type(name: \"B\") { fields { name } } }";
assert_eq!(
schema.execute(query).await.data,
value!({
"__type": {
"fields": [
{"name": "a"},
{"name": "b"},
{"name": "c"}
]
}
})
);
let query = "{ obj { a b c } }";
assert_eq!(
schema.execute(query).await.data,
value!({
"obj": {
"a": 100,
"b": 200,
"c": 300,
}
})
);
}

56
tests/simple_object.rs Normal file
View File

@ -0,0 +1,56 @@
use async_graphql::*;
#[tokio::test]
async fn test_flatten() {
#[derive(SimpleObject)]
struct A {
a: i32,
b: i32,
}
#[derive(SimpleObject)]
struct B {
#[graphql(flatten)]
a: A,
c: i32,
}
struct Query;
#[Object]
impl Query {
async fn obj(&self) -> B {
B {
a: A { a: 100, b: 200 },
c: 300,
}
}
}
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
let query = "{ __type(name: \"B\") { fields { name } } }";
assert_eq!(
schema.execute(query).await.data,
value!({
"__type": {
"fields": [
{"name": "a"},
{"name": "b"},
{"name": "c"}
]
}
})
);
let query = "{ obj { a b c } }";
assert_eq!(
schema.execute(query).await.data,
value!({
"obj": {
"a": 100,
"b": 200,
"c": 300,
}
})
);
}