Merge pull request #1025 from damienpontifex/federation-shareable
This commit is contained in:
commit
0204709de9
|
@ -151,6 +151,8 @@ pub struct SimpleObjectField {
|
||||||
#[darling(default)]
|
#[darling(default)]
|
||||||
pub requires: Option<String>,
|
pub requires: Option<String>,
|
||||||
#[darling(default)]
|
#[darling(default)]
|
||||||
|
pub shareable: bool,
|
||||||
|
#[darling(default)]
|
||||||
pub guard: Option<SpannedValue<String>>,
|
pub guard: Option<SpannedValue<String>>,
|
||||||
#[darling(default)]
|
#[darling(default)]
|
||||||
pub visible: Option<Visible>,
|
pub visible: Option<Visible>,
|
||||||
|
@ -198,6 +200,8 @@ pub struct SimpleObject {
|
||||||
#[darling(default)]
|
#[darling(default)]
|
||||||
pub extends: bool,
|
pub extends: bool,
|
||||||
#[darling(default)]
|
#[darling(default)]
|
||||||
|
pub shareable: bool,
|
||||||
|
#[darling(default)]
|
||||||
pub visible: Option<Visible>,
|
pub visible: Option<Visible>,
|
||||||
#[darling(default, multiple, rename = "concrete")]
|
#[darling(default, multiple, rename = "concrete")]
|
||||||
pub concretes: Vec<ConcreteType>,
|
pub concretes: Vec<ConcreteType>,
|
||||||
|
@ -235,6 +239,7 @@ pub struct Object {
|
||||||
pub rename_args: Option<RenameRule>,
|
pub rename_args: Option<RenameRule>,
|
||||||
pub cache_control: CacheControl,
|
pub cache_control: CacheControl,
|
||||||
pub extends: bool,
|
pub extends: bool,
|
||||||
|
pub shareable: bool,
|
||||||
pub use_type_description: bool,
|
pub use_type_description: bool,
|
||||||
pub visible: Option<Visible>,
|
pub visible: Option<Visible>,
|
||||||
pub serial: bool,
|
pub serial: bool,
|
||||||
|
@ -278,6 +283,7 @@ pub struct ObjectField {
|
||||||
pub external: bool,
|
pub external: bool,
|
||||||
pub provides: Option<String>,
|
pub provides: Option<String>,
|
||||||
pub requires: Option<String>,
|
pub requires: Option<String>,
|
||||||
|
pub shareable: bool,
|
||||||
pub guard: Option<SpannedValue<String>>,
|
pub guard: Option<SpannedValue<String>>,
|
||||||
pub visible: Option<Visible>,
|
pub visible: Option<Visible>,
|
||||||
pub complexity: Option<ComplexityType>,
|
pub complexity: Option<ComplexityType>,
|
||||||
|
@ -491,6 +497,8 @@ pub struct InterfaceField {
|
||||||
pub requires: Option<String>,
|
pub requires: Option<String>,
|
||||||
#[darling(default)]
|
#[darling(default)]
|
||||||
pub visible: Option<Visible>,
|
pub visible: Option<Visible>,
|
||||||
|
#[darling(default)]
|
||||||
|
pub shareable: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromVariant)]
|
#[derive(FromVariant)]
|
||||||
|
@ -594,6 +602,8 @@ pub struct MergedObject {
|
||||||
#[darling(default)]
|
#[darling(default)]
|
||||||
pub extends: bool,
|
pub extends: bool,
|
||||||
#[darling(default)]
|
#[darling(default)]
|
||||||
|
pub shareable: bool,
|
||||||
|
#[darling(default)]
|
||||||
pub visible: Option<Visible>,
|
pub visible: Option<Visible>,
|
||||||
#[darling(default)]
|
#[darling(default)]
|
||||||
pub serial: bool,
|
pub serial: bool,
|
||||||
|
@ -764,6 +774,7 @@ pub struct ComplexObjectField {
|
||||||
pub external: bool,
|
pub external: bool,
|
||||||
pub provides: Option<String>,
|
pub provides: Option<String>,
|
||||||
pub requires: Option<String>,
|
pub requires: Option<String>,
|
||||||
|
pub shareable: bool,
|
||||||
pub guard: Option<SpannedValue<String>>,
|
pub guard: Option<SpannedValue<String>>,
|
||||||
pub visible: Option<Visible>,
|
pub visible: Option<Visible>,
|
||||||
pub complexity: Option<ComplexityType>,
|
pub complexity: Option<ComplexityType>,
|
||||||
|
|
|
@ -172,6 +172,7 @@ pub fn generate(
|
||||||
.unwrap_or_else(|| quote! {::std::option::Option::None});
|
.unwrap_or_else(|| quote! {::std::option::Option::None});
|
||||||
let field_deprecation = gen_deprecation(&method_args.deprecation, &crate_name);
|
let field_deprecation = gen_deprecation(&method_args.deprecation, &crate_name);
|
||||||
let external = method_args.external;
|
let external = method_args.external;
|
||||||
|
let shareable = method_args.shareable;
|
||||||
let requires = match &method_args.requires {
|
let requires = match &method_args.requires {
|
||||||
Some(requires) => quote! { ::std::option::Option::Some(#requires) },
|
Some(requires) => quote! { ::std::option::Option::Some(#requires) },
|
||||||
None => quote! { ::std::option::Option::None },
|
None => quote! { ::std::option::Option::None },
|
||||||
|
@ -365,6 +366,7 @@ pub fn generate(
|
||||||
external: #external,
|
external: #external,
|
||||||
provides: #provides,
|
provides: #provides,
|
||||||
requires: #requires,
|
requires: #requires,
|
||||||
|
shareable: #shareable,
|
||||||
visible: #visible,
|
visible: #visible,
|
||||||
compute_complexity: #complexity,
|
compute_complexity: #complexity,
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -137,6 +137,7 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult<TokenStream
|
||||||
provides,
|
provides,
|
||||||
requires,
|
requires,
|
||||||
visible,
|
visible,
|
||||||
|
shareable,
|
||||||
} in &interface_args.fields
|
} in &interface_args.fields
|
||||||
{
|
{
|
||||||
let (name, method_name) = if let Some(method) = method {
|
let (name, method_name) = if let Some(method) = method {
|
||||||
|
@ -274,6 +275,7 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult<TokenStream
|
||||||
external: #external,
|
external: #external,
|
||||||
provides: #provides,
|
provides: #provides,
|
||||||
requires: #requires,
|
requires: #requires,
|
||||||
|
shareable: #shareable,
|
||||||
visible: #visible,
|
visible: #visible,
|
||||||
compute_complexity: ::std::option::Option::None,
|
compute_complexity: ::std::option::Option::None,
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,6 +14,7 @@ pub fn generate(object_args: &args::MergedObject) -> GeneratorResult<TokenStream
|
||||||
let ident = &object_args.ident;
|
let ident = &object_args.ident;
|
||||||
let (impl_generics, ty_generics, where_clause) = object_args.generics.split_for_impl();
|
let (impl_generics, ty_generics, where_clause) = object_args.generics.split_for_impl();
|
||||||
let extends = object_args.extends;
|
let extends = object_args.extends;
|
||||||
|
let shareable = object_args.shareable;
|
||||||
let gql_typename = object_args
|
let gql_typename = object_args
|
||||||
.name
|
.name
|
||||||
.clone()
|
.clone()
|
||||||
|
@ -103,6 +104,7 @@ pub fn generate(object_args: &args::MergedObject) -> GeneratorResult<TokenStream
|
||||||
fields,
|
fields,
|
||||||
cache_control,
|
cache_control,
|
||||||
extends: #extends,
|
extends: #extends,
|
||||||
|
shareable: #shareable,
|
||||||
keys: ::std::option::Option::None,
|
keys: ::std::option::Option::None,
|
||||||
visible: #visible,
|
visible: #visible,
|
||||||
is_subscription: false,
|
is_subscription: false,
|
||||||
|
|
|
@ -74,6 +74,7 @@ pub fn generate(object_args: &args::MergedSubscription) -> GeneratorResult<Token
|
||||||
extends: #extends,
|
extends: #extends,
|
||||||
keys: ::std::option::Option::None,
|
keys: ::std::option::Option::None,
|
||||||
visible: #visible,
|
visible: #visible,
|
||||||
|
shareable: false,
|
||||||
is_subscription: true,
|
is_subscription: true,
|
||||||
rust_typename: ::std::any::type_name::<Self>(),
|
rust_typename: ::std::any::type_name::<Self>(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ pub fn generate(
|
||||||
let (self_ty, self_name) = get_type_path_and_name(item_impl.self_ty.as_ref())?;
|
let (self_ty, self_name) = get_type_path_and_name(item_impl.self_ty.as_ref())?;
|
||||||
let (impl_generics, _, where_clause) = item_impl.generics.split_for_impl();
|
let (impl_generics, _, where_clause) = item_impl.generics.split_for_impl();
|
||||||
let extends = object_args.extends;
|
let extends = object_args.extends;
|
||||||
|
let shareable = object_args.shareable;
|
||||||
let gql_typename = if !object_args.name_type {
|
let gql_typename = if !object_args.name_type {
|
||||||
object_args
|
object_args
|
||||||
.name
|
.name
|
||||||
|
@ -315,6 +316,7 @@ pub fn generate(
|
||||||
.unwrap_or_else(|| quote! {::std::option::Option::None});
|
.unwrap_or_else(|| quote! {::std::option::Option::None});
|
||||||
let field_deprecation = gen_deprecation(&method_args.deprecation, &crate_name);
|
let field_deprecation = gen_deprecation(&method_args.deprecation, &crate_name);
|
||||||
let external = method_args.external;
|
let external = method_args.external;
|
||||||
|
let shareable = method_args.shareable;
|
||||||
let requires = match &method_args.requires {
|
let requires = match &method_args.requires {
|
||||||
Some(requires) => quote! { ::std::option::Option::Some(#requires) },
|
Some(requires) => quote! { ::std::option::Option::Some(#requires) },
|
||||||
None => quote! { ::std::option::Option::None },
|
None => quote! { ::std::option::Option::None },
|
||||||
|
@ -507,6 +509,7 @@ pub fn generate(
|
||||||
external: #external,
|
external: #external,
|
||||||
provides: #provides,
|
provides: #provides,
|
||||||
requires: #requires,
|
requires: #requires,
|
||||||
|
shareable: #shareable,
|
||||||
visible: #visible,
|
visible: #visible,
|
||||||
compute_complexity: #complexity,
|
compute_complexity: #complexity,
|
||||||
});
|
});
|
||||||
|
@ -640,6 +643,7 @@ pub fn generate(
|
||||||
},
|
},
|
||||||
cache_control: #cache_control,
|
cache_control: #cache_control,
|
||||||
extends: #extends,
|
extends: #extends,
|
||||||
|
shareable: #shareable,
|
||||||
keys: ::std::option::Option::None,
|
keys: ::std::option::Option::None,
|
||||||
visible: #visible,
|
visible: #visible,
|
||||||
is_subscription: false,
|
is_subscription: false,
|
||||||
|
@ -679,6 +683,7 @@ pub fn generate(
|
||||||
},
|
},
|
||||||
cache_control: #cache_control,
|
cache_control: #cache_control,
|
||||||
extends: #extends,
|
extends: #extends,
|
||||||
|
shareable: #shareable,
|
||||||
keys: ::std::option::Option::None,
|
keys: ::std::option::Option::None,
|
||||||
visible: #visible,
|
visible: #visible,
|
||||||
is_subscription: false,
|
is_subscription: false,
|
||||||
|
|
|
@ -30,6 +30,7 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
||||||
let ident = &object_args.ident;
|
let ident = &object_args.ident;
|
||||||
let (impl_generics, ty_generics, where_clause) = object_args.generics.split_for_impl();
|
let (impl_generics, ty_generics, where_clause) = object_args.generics.split_for_impl();
|
||||||
let extends = object_args.extends;
|
let extends = object_args.extends;
|
||||||
|
let shareable = object_args.shareable;
|
||||||
let gql_typename = if !object_args.name_type {
|
let gql_typename = if !object_args.name_type {
|
||||||
object_args
|
object_args
|
||||||
.name
|
.name
|
||||||
|
@ -127,6 +128,7 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
||||||
.unwrap_or_else(|| quote! {::std::option::Option::None});
|
.unwrap_or_else(|| quote! {::std::option::Option::None});
|
||||||
let field_deprecation = gen_deprecation(&field.deprecation, &crate_name);
|
let field_deprecation = gen_deprecation(&field.deprecation, &crate_name);
|
||||||
let external = field.external;
|
let external = field.external;
|
||||||
|
let shareable = field.shareable;
|
||||||
let requires = match &field.requires {
|
let requires = match &field.requires {
|
||||||
Some(requires) => quote! { ::std::option::Option::Some(#requires) },
|
Some(requires) => quote! { ::std::option::Option::Some(#requires) },
|
||||||
None => quote! { ::std::option::Option::None },
|
None => quote! { ::std::option::Option::None },
|
||||||
|
@ -174,6 +176,7 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
||||||
external: #external,
|
external: #external,
|
||||||
provides: #provides,
|
provides: #provides,
|
||||||
requires: #requires,
|
requires: #requires,
|
||||||
|
shareable: #shareable,
|
||||||
visible: #visible,
|
visible: #visible,
|
||||||
compute_complexity: ::std::option::Option::None,
|
compute_complexity: ::std::option::Option::None,
|
||||||
});
|
});
|
||||||
|
@ -329,6 +332,7 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
||||||
},
|
},
|
||||||
cache_control: #cache_control,
|
cache_control: #cache_control,
|
||||||
extends: #extends,
|
extends: #extends,
|
||||||
|
shareable: #shareable,
|
||||||
keys: ::std::option::Option::None,
|
keys: ::std::option::Option::None,
|
||||||
visible: #visible,
|
visible: #visible,
|
||||||
is_subscription: false,
|
is_subscription: false,
|
||||||
|
@ -393,6 +397,7 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
||||||
},
|
},
|
||||||
cache_control: #cache_control,
|
cache_control: #cache_control,
|
||||||
extends: #extends,
|
extends: #extends,
|
||||||
|
shareable: #shareable,
|
||||||
keys: ::std::option::Option::None,
|
keys: ::std::option::Option::None,
|
||||||
visible: #visible,
|
visible: #visible,
|
||||||
is_subscription: false,
|
is_subscription: false,
|
||||||
|
|
|
@ -267,6 +267,7 @@ pub fn generate(
|
||||||
external: false,
|
external: false,
|
||||||
requires: ::std::option::Option::None,
|
requires: ::std::option::Option::None,
|
||||||
provides: ::std::option::Option::None,
|
provides: ::std::option::Option::None,
|
||||||
|
shareable: false,
|
||||||
visible: #visible,
|
visible: #visible,
|
||||||
compute_complexity: #complexity,
|
compute_complexity: #complexity,
|
||||||
});
|
});
|
||||||
|
@ -408,6 +409,7 @@ pub fn generate(
|
||||||
extends: #extends,
|
extends: #extends,
|
||||||
keys: ::std::option::Option::None,
|
keys: ::std::option::Option::None,
|
||||||
visible: #visible,
|
visible: #visible,
|
||||||
|
shareable: false,
|
||||||
is_subscription: true,
|
is_subscription: true,
|
||||||
rust_typename: ::std::any::type_name::<Self>(),
|
rust_typename: ::std::any::type_name::<Self>(),
|
||||||
})
|
})
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
- The `requires` directive is used to 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.
|
- The `requires` directive is used to 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.
|
||||||
|
|
||||||
|
- The `shareable` directive is used to indicate that an object type's field is allowed to be resolved by multiple subgraphs (by default, each field can be resolved by only one subgraph).
|
||||||
|
|
||||||
## Entity lookup function
|
## Entity lookup function
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
|
|
@ -30,6 +30,7 @@ some simple fields, and use the `ComplexObject` macro to define some other field
|
||||||
| 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
||||||
|
| shareable | Indicate that a field is allowed to be resolved by multiple subgraphs | bool | Y |
|
||||||
| guard | Field of guard *[See also the Book](https://async-graphql.github.io/async-graphql/en/field_guard.html)* | 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 | 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 |
|
| visible | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
|
||||||
|
|
|
@ -13,6 +13,7 @@ All methods are converted to camelCase.
|
||||||
| 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 |
|
| 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 |
|
| cache_control | Object cache control | [`CacheControl`](struct.CacheControl.html) | Y |
|
||||||
| extends | Add fields to an entity that's defined in another service | bool | Y |
|
| extends | Add fields to an entity that's defined in another service | bool | Y |
|
||||||
|
| shareable | Indicate that an object type's field is allowed to be resolved by multiple subgraphs | bool | Y |
|
||||||
| use_type_description | Specifies that the description of the type is on the type declaration. [`Description`]()(derive.Description.html) | 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 | 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 |
|
| visible | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
|
||||||
|
@ -33,6 +34,7 @@ All methods are converted to camelCase.
|
||||||
| 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
||||||
|
| shareable | Indicate that a field is allowed to be resolved by multiple subgraphs | bool | Y |
|
||||||
| guard | Field of guard *[See also the Book](https://async-graphql.github.io/async-graphql/en/field_guard.html)* | 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 | 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 |
|
| visible | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
|
||||||
|
|
|
@ -12,6 +12,7 @@ Similar to `Object`, but defined on a structure that automatically generates get
|
||||||
| 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_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 |
|
| cache_control | Object cache control | [`CacheControl`](struct.CacheControl.html) | Y |
|
||||||
| extends | Add fields to an entity that's defined in another service | bool | Y |
|
| extends | Add fields to an entity that's defined in another service | bool | Y |
|
||||||
|
| shareable | Indicate that an object type's field is allowed to be resolved by multiple subgraphs | 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 | 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 |
|
| 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 |
|
| 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 |
|
||||||
|
@ -33,6 +34,7 @@ Similar to `Object`, but defined on a structure that automatically generates get
|
||||||
| 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
||||||
|
| shareable | Indicate that a field is allowed to be resolved by multiple subgraphs | bool | Y |
|
||||||
| guard | Field of guard *[See also the Book](https://async-graphql.github.io/async-graphql/en/field_guard.html)* | 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 | 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 |
|
| visible | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
|
||||||
|
|
|
@ -170,6 +170,9 @@ impl Registry {
|
||||||
if let Some(provides) = field.provides {
|
if let Some(provides) = field.provides {
|
||||||
write!(sdl, " @provides(fields: \"{}\")", provides).ok();
|
write!(sdl, " @provides(fields: \"{}\")", provides).ok();
|
||||||
}
|
}
|
||||||
|
if field.shareable {
|
||||||
|
write!(sdl, " @shareable").ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writeln!(sdl).ok();
|
writeln!(sdl).ok();
|
||||||
|
@ -198,6 +201,7 @@ impl Registry {
|
||||||
extends,
|
extends,
|
||||||
keys,
|
keys,
|
||||||
description,
|
description,
|
||||||
|
shareable,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
if Some(name.as_str()) == self.subscription_type.as_deref()
|
if Some(name.as_str()) == self.subscription_type.as_deref()
|
||||||
|
@ -241,6 +245,9 @@ impl Registry {
|
||||||
write!(sdl, "@key(fields: \"{}\") ", key).ok();
|
write!(sdl, "@key(fields: \"{}\") ", key).ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if *shareable {
|
||||||
|
write!(sdl, "@shareable ").ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writeln!(sdl, "{{").ok();
|
writeln!(sdl, "{{").ok();
|
||||||
|
|
|
@ -166,6 +166,7 @@ pub struct MetaField {
|
||||||
pub requires: Option<&'static str>,
|
pub requires: Option<&'static str>,
|
||||||
pub provides: Option<&'static str>,
|
pub provides: Option<&'static str>,
|
||||||
pub visible: Option<MetaVisibleFn>,
|
pub visible: Option<MetaVisibleFn>,
|
||||||
|
pub shareable: bool,
|
||||||
pub compute_complexity: Option<ComplexityType>,
|
pub compute_complexity: Option<ComplexityType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,6 +218,7 @@ pub enum MetaType {
|
||||||
fields: IndexMap<String, MetaField>,
|
fields: IndexMap<String, MetaField>,
|
||||||
cache_control: CacheControl,
|
cache_control: CacheControl,
|
||||||
extends: bool,
|
extends: bool,
|
||||||
|
shareable: bool,
|
||||||
keys: Option<Vec<String>>,
|
keys: Option<Vec<String>>,
|
||||||
visible: Option<MetaVisibleFn>,
|
visible: Option<MetaVisibleFn>,
|
||||||
is_subscription: bool,
|
is_subscription: bool,
|
||||||
|
@ -492,6 +494,7 @@ impl Registry {
|
||||||
fields: Default::default(),
|
fields: Default::default(),
|
||||||
cache_control: Default::default(),
|
cache_control: Default::default(),
|
||||||
extends: false,
|
extends: false,
|
||||||
|
shareable: false,
|
||||||
keys: None,
|
keys: None,
|
||||||
visible: None,
|
visible: None,
|
||||||
is_subscription: false,
|
is_subscription: false,
|
||||||
|
@ -619,6 +622,7 @@ impl Registry {
|
||||||
external: false,
|
external: false,
|
||||||
requires: None,
|
requires: None,
|
||||||
provides: None,
|
provides: None,
|
||||||
|
shareable: false,
|
||||||
visible: None,
|
visible: None,
|
||||||
compute_complexity: None,
|
compute_complexity: None,
|
||||||
},
|
},
|
||||||
|
@ -664,6 +668,7 @@ impl Registry {
|
||||||
external: false,
|
external: false,
|
||||||
requires: None,
|
requires: None,
|
||||||
provides: None,
|
provides: None,
|
||||||
|
shareable: false,
|
||||||
visible: None,
|
visible: None,
|
||||||
compute_complexity: None,
|
compute_complexity: None,
|
||||||
},
|
},
|
||||||
|
@ -694,6 +699,7 @@ impl Registry {
|
||||||
external: false,
|
external: false,
|
||||||
requires: None,
|
requires: None,
|
||||||
provides: None,
|
provides: None,
|
||||||
|
shareable: false,
|
||||||
visible: None,
|
visible: None,
|
||||||
compute_complexity: None,
|
compute_complexity: None,
|
||||||
},
|
},
|
||||||
|
@ -702,6 +708,7 @@ impl Registry {
|
||||||
},
|
},
|
||||||
cache_control: Default::default(),
|
cache_control: Default::default(),
|
||||||
extends: false,
|
extends: false,
|
||||||
|
shareable: false,
|
||||||
keys: None,
|
keys: None,
|
||||||
visible: None,
|
visible: None,
|
||||||
is_subscription: false,
|
is_subscription: false,
|
||||||
|
|
|
@ -54,6 +54,7 @@ impl OutputType for EmptyMutation {
|
||||||
fields: Default::default(),
|
fields: Default::default(),
|
||||||
cache_control: Default::default(),
|
cache_control: Default::default(),
|
||||||
extends: false,
|
extends: false,
|
||||||
|
shareable: false,
|
||||||
keys: None,
|
keys: None,
|
||||||
visible: None,
|
visible: None,
|
||||||
is_subscription: false,
|
is_subscription: false,
|
||||||
|
|
|
@ -23,6 +23,7 @@ impl SubscriptionType for EmptySubscription {
|
||||||
fields: Default::default(),
|
fields: Default::default(),
|
||||||
cache_control: Default::default(),
|
cache_control: Default::default(),
|
||||||
extends: false,
|
extends: false,
|
||||||
|
shareable: false,
|
||||||
keys: None,
|
keys: None,
|
||||||
visible: None,
|
visible: None,
|
||||||
is_subscription: true,
|
is_subscription: true,
|
||||||
|
|
|
@ -77,6 +77,7 @@ where
|
||||||
fields,
|
fields,
|
||||||
cache_control: cc,
|
cache_control: cc,
|
||||||
extends: false,
|
extends: false,
|
||||||
|
shareable: false,
|
||||||
keys: None,
|
keys: None,
|
||||||
visible: None,
|
visible: None,
|
||||||
is_subscription: false,
|
is_subscription: false,
|
||||||
|
@ -135,6 +136,7 @@ where
|
||||||
fields,
|
fields,
|
||||||
cache_control: cc,
|
cache_control: cc,
|
||||||
extends: false,
|
extends: false,
|
||||||
|
shareable: false,
|
||||||
keys: None,
|
keys: None,
|
||||||
visible: None,
|
visible: None,
|
||||||
is_subscription: false,
|
is_subscription: false,
|
||||||
|
@ -168,6 +170,7 @@ impl SubscriptionType for MergedObjectTail {
|
||||||
fields: Default::default(),
|
fields: Default::default(),
|
||||||
cache_control: Default::default(),
|
cache_control: Default::default(),
|
||||||
extends: false,
|
extends: false,
|
||||||
|
shareable: false,
|
||||||
keys: None,
|
keys: None,
|
||||||
visible: None,
|
visible: None,
|
||||||
is_subscription: false,
|
is_subscription: false,
|
||||||
|
|
|
@ -131,6 +131,7 @@ impl<T: ObjectType> OutputType for QueryRoot<T> {
|
||||||
external: false,
|
external: false,
|
||||||
requires: None,
|
requires: None,
|
||||||
provides: None,
|
provides: None,
|
||||||
|
shareable: false,
|
||||||
visible: None,
|
visible: None,
|
||||||
compute_complexity: None,
|
compute_complexity: None,
|
||||||
},
|
},
|
||||||
|
@ -162,6 +163,7 @@ impl<T: ObjectType> OutputType for QueryRoot<T> {
|
||||||
external: false,
|
external: false,
|
||||||
requires: None,
|
requires: None,
|
||||||
provides: None,
|
provides: None,
|
||||||
|
shareable: false,
|
||||||
visible: None,
|
visible: None,
|
||||||
compute_complexity: None,
|
compute_complexity: None,
|
||||||
},
|
},
|
||||||
|
|
|
@ -286,3 +286,44 @@ pub async fn test_entity_union() {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
pub async fn test_entity_shareable() {
|
||||||
|
#[derive(SimpleObject)]
|
||||||
|
struct MyObjFieldShareable {
|
||||||
|
#[graphql(shareable)]
|
||||||
|
field_shareable_a: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(SimpleObject)]
|
||||||
|
#[graphql(shareable)]
|
||||||
|
struct MyObjShareable {
|
||||||
|
a: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Query;
|
||||||
|
|
||||||
|
#[Object(extends)]
|
||||||
|
impl Query {
|
||||||
|
#[graphql(entity)]
|
||||||
|
async fn find_obj_field_shareable(&self, _id: i32) -> MyObjFieldShareable {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
#[graphql(entity)]
|
||||||
|
async fn find_obj_shareable(&self, _id: i32) -> MyObjShareable {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let schema_sdl = Schema::new(Query, EmptyMutation, EmptySubscription)
|
||||||
|
.sdl_with_options(SDLExportOptions::new().federation());
|
||||||
|
assert_eq!(
|
||||||
|
schema_sdl.contains("fieldShareableA: Int! @shareable"),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
schema_sdl.contains(r#"MyObjShareable @key(fields: "id") @shareable"#),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user