[][src]Derive Macro async_graphql::Interface

#[derive(Interface)]
{
    // Attributes available to this derive:
    #[graphql]
}

Define a GraphQL interface

See also the Book.

Macro parameters

AttributedescriptionTypeOptional
nameObject namestringY
fieldFields of this Interface[InterfaceField]N
extendsAdd fields to an entity that's defined in another serviceboolY

Field parameters

AttributedescriptionTypeOptional
nameField namestringN
typeField typestringN
methodRust resolver method name. If specified, name will not be camelCased in schema definitionstringY
descField descriptionstringY
deprecationField deprecation reasonstringY
argField arguments[InterfaceFieldArgument]Y
externalMark 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.boolY
providesAnnotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway.stringY
requiresAnnotate 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.stringY

Field argument parameters

AttributedescriptionTypeOptional
nameArgument namestringN
typeArgument typestringN
descArgument descriptionstringY
defaultUse Default::default for default valuenoneY
defaultArgument default valueliteralY
default_withExpression to generate default valuecode stringY

Define an interface

Define TypeA, TypeB, TypeC... Implement the MyInterface

This example is not tested
#[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 FieldResult can be omitted.

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<'_>) -> FieldResult<&'a str> {
        Ok(ctx.data::<String>()?.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 QueryRoot;

#[Object]
impl QueryRoot {
    async fn type_a(&self) -> MyInterface {
        TypeA { value: 10 }.into()
    }
}

async_std::task::block_on(async move {
    let schema = Schema::build(QueryRoot, 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, serde_json::json!({
        "typeA": {
            "valueA": "hello",
            "valueB": 10,
            "valueC": 5,
            "value_d": 11
        }
    }));
});