diff --git a/derive/src/args.rs b/derive/src/args.rs index 88c154c2..250cf2ac 100644 --- a/derive/src/args.rs +++ b/derive/src/args.rs @@ -155,6 +155,8 @@ pub struct SimpleObjectField { #[darling(default)] pub inaccessible: bool, #[darling(default)] + pub override_from: Option, + #[darling(default)] pub guard: Option>, #[darling(default)] pub visible: Option, @@ -291,6 +293,7 @@ pub struct ObjectField { pub requires: Option, pub shareable: bool, pub inaccessible: bool, + pub override_from: Option, pub guard: Option>, pub visible: Option, pub complexity: Option, @@ -524,6 +527,8 @@ pub struct InterfaceField { pub inaccessible: bool, #[darling(default)] pub shareable: bool, + #[darling(default)] + pub override_from: Option, } #[derive(FromVariant)] @@ -808,6 +813,7 @@ pub struct ComplexObjectField { pub requires: Option, pub shareable: bool, pub inaccessible: bool, + pub override_from: Option, pub guard: Option>, pub visible: Option, pub complexity: Option, diff --git a/derive/src/complex_object.rs b/derive/src/complex_object.rs index 0329a2e6..8630e2cb 100644 --- a/derive/src/complex_object.rs +++ b/derive/src/complex_object.rs @@ -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, })); diff --git a/derive/src/interface.rs b/derive/src/interface.rs index 962a152a..e14284ca 100644 --- a/derive/src/interface.rs +++ b/derive/src/interface.rs @@ -140,6 +140,7 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult GeneratorResult 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 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, }); diff --git a/derive/src/simple_object.rs b/derive/src/simple_object.rs index 37088634..35f6b358 100644 --- a/derive/src/simple_object.rs +++ b/derive/src/simple_object.rs @@ -131,6 +131,10 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult 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, pub shareable: bool, pub inaccessible: bool, + pub override_from: Option<&'static str>, pub compute_complexity: Option, } @@ -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, }, ); diff --git a/src/types/query_root.rs b/src/types/query_root.rs index f38cdfb5..93d3d977 100644 --- a/src/types/query_root.rs +++ b/src/types/query_root.rs @@ -135,6 +135,7 @@ impl OutputType for QueryRoot { inaccessible: false, visible: None, compute_complexity: None, + override_from: None, }, ); @@ -167,6 +168,7 @@ impl OutputType for QueryRoot { provides: None, shareable: false, inaccessible: false, + override_from: None, visible: None, compute_complexity: None, }, diff --git a/tests/federation.rs b/tests/federation.rs index 6dccdf9b..0a48bd27 100644 --- a/tests/federation.rs +++ b/tests/federation.rs @@ -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;