define override directive on fields
* define the directive field on the field struct * implement printing it on the federation sdl * update the derive stuff * add a test
This commit is contained in:
parent
f84781bf08
commit
6f57a13b71
|
@ -155,6 +155,8 @@ pub struct SimpleObjectField {
|
|||
#[darling(default)]
|
||||
pub inaccessible: bool,
|
||||
#[darling(default)]
|
||||
pub override_from: Option<String>,
|
||||
#[darling(default)]
|
||||
pub guard: Option<SpannedValue<String>>,
|
||||
#[darling(default)]
|
||||
pub visible: Option<Visible>,
|
||||
|
@ -291,6 +293,7 @@ pub struct ObjectField {
|
|||
pub requires: Option<String>,
|
||||
pub shareable: bool,
|
||||
pub inaccessible: bool,
|
||||
pub override_from: Option<String>,
|
||||
pub guard: Option<SpannedValue<String>>,
|
||||
pub visible: Option<Visible>,
|
||||
pub complexity: Option<ComplexityType>,
|
||||
|
@ -524,6 +527,8 @@ pub struct InterfaceField {
|
|||
pub inaccessible: bool,
|
||||
#[darling(default)]
|
||||
pub shareable: bool,
|
||||
#[darling(default)]
|
||||
pub override_from: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(FromVariant)]
|
||||
|
@ -808,6 +813,7 @@ pub struct ComplexObjectField {
|
|||
pub requires: Option<String>,
|
||||
pub shareable: bool,
|
||||
pub inaccessible: bool,
|
||||
pub override_from: Option<String>,
|
||||
pub guard: Option<SpannedValue<String>>,
|
||||
pub visible: Option<Visible>,
|
||||
pub complexity: Option<ComplexityType>,
|
||||
|
|
|
@ -173,6 +173,10 @@ pub fn generate(
|
|||
let field_deprecation = gen_deprecation(&method_args.deprecation, &crate_name);
|
||||
let external = method_args.external;
|
||||
let shareable = method_args.shareable;
|
||||
let override_from = match &method_args.override_from {
|
||||
Some(from) => quote! { ::std::option::Option::Some(#from) },
|
||||
None => quote! { ::std::option::Option::None },
|
||||
};
|
||||
let inaccessible = method_args.inaccessible;
|
||||
let requires = match &method_args.requires {
|
||||
Some(requires) => quote! { ::std::option::Option::Some(#requires) },
|
||||
|
@ -371,6 +375,7 @@ pub fn generate(
|
|||
requires: #requires,
|
||||
shareable: #shareable,
|
||||
inaccessible: #inaccessible,
|
||||
override_from: #override_from,
|
||||
visible: #visible,
|
||||
compute_complexity: #complexity,
|
||||
}));
|
||||
|
|
|
@ -140,6 +140,7 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult<TokenStream
|
|||
visible,
|
||||
shareable,
|
||||
inaccessible,
|
||||
override_from,
|
||||
} in &interface_args.fields
|
||||
{
|
||||
let (name, method_name) = if let Some(method) = method {
|
||||
|
@ -170,6 +171,10 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult<TokenStream
|
|||
Some(provides) => quote! { ::std::option::Option::Some(#provides) },
|
||||
None => quote! { ::std::option::Option::None },
|
||||
};
|
||||
let override_from = match &override_from {
|
||||
Some(from) => quote! { ::std::option::Option::Some(#from) },
|
||||
None => quote! { ::std::option::Option::None },
|
||||
};
|
||||
|
||||
decl_params.push(quote! { ctx: &'ctx #crate_name::Context<'ctx> });
|
||||
use_params.push(quote! { ctx });
|
||||
|
@ -281,6 +286,7 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult<TokenStream
|
|||
requires: #requires,
|
||||
shareable: #shareable,
|
||||
inaccessible: #inaccessible,
|
||||
override_from: #override_from,
|
||||
visible: #visible,
|
||||
compute_complexity: ::std::option::Option::None,
|
||||
});
|
||||
|
|
|
@ -319,6 +319,10 @@ pub fn generate(
|
|||
let external = method_args.external;
|
||||
let shareable = method_args.shareable;
|
||||
let inaccessible = method_args.inaccessible;
|
||||
let override_from = match &method_args.override_from {
|
||||
Some(from) => quote! { ::std::option::Option::Some(#from) },
|
||||
None => quote! { ::std::option::Option::None },
|
||||
};
|
||||
let requires = match &method_args.requires {
|
||||
Some(requires) => quote! { ::std::option::Option::Some(#requires) },
|
||||
None => quote! { ::std::option::Option::None },
|
||||
|
@ -515,6 +519,7 @@ pub fn generate(
|
|||
requires: #requires,
|
||||
shareable: #shareable,
|
||||
inaccessible: #inaccessible,
|
||||
override_from: #override_from,
|
||||
visible: #visible,
|
||||
compute_complexity: #complexity,
|
||||
});
|
||||
|
|
|
@ -131,6 +131,10 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
|||
let external = field.external;
|
||||
let shareable = field.shareable;
|
||||
let inaccessible = field.inaccessible;
|
||||
let override_from = match &field.override_from {
|
||||
Some(from) => quote! { ::std::option::Option::Some(#from) },
|
||||
None => quote! { ::std::option::Option::None },
|
||||
};
|
||||
let requires = match &field.requires {
|
||||
Some(requires) => quote! { ::std::option::Option::Some(#requires) },
|
||||
None => quote! { ::std::option::Option::None },
|
||||
|
@ -180,6 +184,7 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
|||
requires: #requires,
|
||||
shareable: #shareable,
|
||||
inaccessible: #inaccessible,
|
||||
override_from: #override_from,
|
||||
visible: #visible,
|
||||
compute_complexity: ::std::option::Option::None,
|
||||
});
|
||||
|
|
|
@ -269,6 +269,7 @@ pub fn generate(
|
|||
requires: ::std::option::Option::None,
|
||||
provides: ::std::option::Option::None,
|
||||
shareable: false,
|
||||
override_from: ::std::option::Option::None,
|
||||
visible: #visible,
|
||||
inaccessible: false,
|
||||
compute_complexity: #complexity,
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
- The `inaccessible` directive is used to indicate that a location in the schema cannot be queried at the supergraph level, but can still be queried at the subgraph level.
|
||||
|
||||
- The `override` directive is used to indicate that a field is now to be resolved by the current subgraph instead of the named subgraph.
|
||||
|
||||
## Entity lookup function
|
||||
|
||||
```rust
|
||||
|
|
|
@ -33,6 +33,7 @@ some simple fields, and use the `ComplexObject` macro to define some other field
|
|||
| 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 |
|
||||
| inaccessible | Indicate that a field is not accessible from a supergraph when using Apollo Federation | bool | Y |
|
||||
| override_from | Mark the field as overriding a field currently present on another subgraph. It is used to migrate fields between subgraphs. | 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 |
|
||||
|
|
|
@ -17,21 +17,22 @@ Define a GraphQL interface
|
|||
|
||||
# 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 |
|
||||
| inaccessible | Indicate that a field is not accessible from a supergraph when using Apollo Federation | bool | 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 |
|
||||
| override_from | Mark the field as overriding a field currently present on another subgraph. It is used to migrate fields between subgraphs. | 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 |
|
||||
| inaccessible | Indicate that a field is not accessible from a supergraph when using Apollo Federation | bool | Y |
|
||||
|
||||
# Field argument attributes
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ All methods are converted to camelCase.
|
|||
| 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 |
|
||||
| inaccessible | Indicate that a field is not accessible from a supergraph when using Apollo Federation | bool | Y |
|
||||
| override_from | Mark the field as overriding a field currently present on another subgraph. It is used to migrate fields between subgraphs. | 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 |
|
||||
|
|
|
@ -36,8 +36,8 @@ Similar to `Object`, but defined on a structure that automatically generates get
|
|||
| 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 |
|
||||
| shareable | Indicate that a field is allowed to be resolved by multiple subgraphs | bool | Y |
|
||||
|
||||
| inaccessible | Indicate that a field is not accessible from a supergraph when using Apollo Federation | bool | Y |
|
||||
| override_from | Mark the field as overriding a field currently present on another subgraph. It is used to migrate fields between subgraphs. | 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 |
|
||||
|
|
|
@ -180,6 +180,9 @@ impl Registry {
|
|||
if field.inaccessible {
|
||||
write!(sdl, " @inaccessible").ok();
|
||||
}
|
||||
if let Some(from) = field.override_from {
|
||||
write!(sdl, " @override(from: \"{}\")", from).ok();
|
||||
}
|
||||
}
|
||||
|
||||
writeln!(sdl).ok();
|
||||
|
|
|
@ -169,6 +169,7 @@ pub struct MetaField {
|
|||
pub visible: Option<MetaVisibleFn>,
|
||||
pub shareable: bool,
|
||||
pub inaccessible: bool,
|
||||
pub override_from: Option<&'static str>,
|
||||
pub compute_complexity: Option<ComplexityType>,
|
||||
}
|
||||
|
||||
|
@ -634,6 +635,7 @@ impl Registry {
|
|||
provides: None,
|
||||
shareable: false,
|
||||
inaccessible: false,
|
||||
override_from: None,
|
||||
visible: None,
|
||||
compute_complexity: None,
|
||||
},
|
||||
|
@ -684,6 +686,7 @@ impl Registry {
|
|||
shareable: false,
|
||||
visible: None,
|
||||
inaccessible: false,
|
||||
override_from: None,
|
||||
compute_complexity: None,
|
||||
},
|
||||
);
|
||||
|
@ -716,6 +719,7 @@ impl Registry {
|
|||
shareable: false,
|
||||
visible: None,
|
||||
inaccessible: false,
|
||||
override_from: None,
|
||||
compute_complexity: None,
|
||||
},
|
||||
);
|
||||
|
|
|
@ -135,6 +135,7 @@ impl<T: ObjectType> OutputType for QueryRoot<T> {
|
|||
inaccessible: false,
|
||||
visible: None,
|
||||
compute_complexity: None,
|
||||
override_from: None,
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -167,6 +168,7 @@ impl<T: ObjectType> OutputType for QueryRoot<T> {
|
|||
provides: None,
|
||||
shareable: false,
|
||||
inaccessible: false,
|
||||
override_from: None,
|
||||
visible: None,
|
||||
compute_complexity: None,
|
||||
},
|
||||
|
|
|
@ -328,6 +328,32 @@ pub async fn test_entity_shareable() {
|
|||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
pub async fn test_field_override_directive() {
|
||||
#[derive(SimpleObject)]
|
||||
struct MyObjFieldOverride {
|
||||
#[graphql(override_from = "AnotherSubgraph")]
|
||||
field_override_a: i32,
|
||||
}
|
||||
|
||||
struct Query;
|
||||
|
||||
#[Object(extends)]
|
||||
impl Query {
|
||||
#[graphql(entity)]
|
||||
async fn find_obj_field_override(&self, _id: i32) -> MyObjFieldOverride {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
let schema_sdl = Schema::new(Query, EmptyMutation, EmptySubscription)
|
||||
.sdl_with_options(SDLExportOptions::new().federation());
|
||||
assert_eq!(
|
||||
schema_sdl.contains("fieldOverrideA: Int! @override(from: \"AnotherSubgraph\")"),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
pub async fn test_entity_inaccessible() {
|
||||
struct MyCustomObjInaccessible;
|
||||
|
|
Loading…
Reference in New Issue