1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
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 |
| inaccessible | Indicate that an interface is not accessible from a supergraph when using Apollo Federation | bool | Y |
| tag | Arbitrary string metadata that will be propagated to the supergraph when using Apollo Federation. This attribute is repeatable | 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 |
| 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 |
| tag | Arbitrary string metadata that will be propagated to the supergraph when using Apollo Federation. This attribute is repeatable | 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 |
| inaccessible | Indicate that an argument is not accessible from a supergraph when using Apollo Federation | bool | Y |
| tag | Arbitrary string metadata that will be propagated to the supergraph when using Apollo Federation. This attribute is repeatable | string | 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::<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 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
}
}));
# });
```