Define a GraphQL interface *[See also the Book](https://async-graphql.github.io/async-graphql/en/define_interface.html).* # 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 | # 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 | # 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 | # Define an interface Define TypeA, TypeB, TypeC... Implement the MyInterface ```ignore #[derive(Interface)] enum MyInterface { TypeA(TypeA), TypeB(TypeB), TypeC(TypeC), ... } ``` # Fields The type, name, and parameter fields of the interface must exactly match the type of the implementation interface, but Result can be omitted. ```rust use async_graphql::*; struct TypeA { value: i32, } #[Object] impl TypeA { /// Returns data borrowed from the context async fn value_a<'a>(&self, ctx: &'a Context<'_>) -> Result<&'a str> { Ok(ctx.data::()?.as_str()) } /// Returns data borrowed self async fn value_b(&self) -> &i32 { &self.value } /// With parameters async fn value_c(&self, a: i32, b: i32) -> i32 { a + b } /// Disabled name transformation, don't forget "method" argument in interface! #[graphql(name = "value_d")] async fn value_d(&self) -> i32 { &self.value + 1 } } #[derive(Interface)] #[graphql( field(name = "value_a", type = "&'ctx str"), field(name = "value_b", type = "&i32"), field(name = "value_c", type = "i32", arg(name = "a", type = "i32"), arg(name = "b", type = "i32")), field(name = "value_d", method = "value_d", type = "i32"), )] enum MyInterface { TypeA(TypeA) } struct Query; #[Object] impl Query { async fn type_a(&self) -> MyInterface { TypeA { value: 10 }.into() } } # tokio::runtime::Runtime::new().unwrap().block_on(async move { let schema = Schema::build(Query, EmptyMutation, EmptySubscription).data("hello".to_string()).finish(); let res = schema.execute(r#" { typeA { valueA valueB valueC(a: 3, b: 2) value_d } }"#).await.into_result().unwrap().data; assert_eq!(res, value!({ "typeA": { "valueA": "hello", "valueB": 10, "valueC": 5, "value_d": 11 } })); # }); ```