Comments (18)
Upgrade to 1.9.4
and take a look at this test.
https://github.com/sunli829/async-graphql/blob/fd156500e316e596a5ae47b40f6d99825b5990f7/tests/interface.rs#L4
from async-graphql.
I see what you mean. You want to return a combination of two interfaces. Let me think for a moment.Because I'm not sure that GraphQL still has this functionality.
from async-graphql.
This is really a big problem, and I'm going to solve it now. Thank you very much.๐
from async-graphql.
Very easy๏ผhere's an example, MyObj
implementedIntefaceA
and InterfaceB
.
struct MyObj;
#[async_graphql::Object]
impl MyObj {
#[field]
async fn value_a(&self) -> i32 {
unimplemented!()
}
#[field]
async fn value_b(&self) -> i32 {
unimplemented!()
}
}
#[async_graphql::Interface(field(name = "value_a", type = "i32"))]
struct InterfaceA(MyObj);
#[async_graphql::Interface(field(name = "value_b", type = "i32"))]
struct InterfaceB(MyObj);
from async-graphql.
I think there might be a problem in representing that structure in a resolver.
If you implement:
pub struct QueryRoot;
#[async_graphql::Object]
impl QueryRoot {
#[field]
async fn my_objs(&self, _ctx: &Context<'_>) -> InterfaceA {
(MyObj {}).into()
}
}
In the above example, the server doesn't know about InterfaceB
and the query execution fails.
I put together a sample repository at https://github.com/phated/async-graphql-interfaces that identifies the problem.
The query that needs to succeed is:
{
myObjs {
... on InterfaceA {
valueA
}
... on InterfaceB {
valueB
}
}
}
from async-graphql.
I've been thinking a lot about Interfaces in GraphQL to support Relay in my data structures and I wonder if they are better represented in Rust by implementing a trait.
What do you think of this API?
struct MyObj;
#[async_graphql::Object]
impl MyObj {
async fn value_c(&self) -> i32 {
3
}
}
// Would the macro go on trait or impl?
#[async_graphql::Interface]
trait InterfaceA {
async fn value_a(&self) -> i32;
}
// Would the macro go on trait or impl?
#[async_graphql::Interface]
trait InterfaceB {
async fn value_b(&self) -> i32;
}
// Maybe it would go on both?
#[async_graphql::Interface]
impl InterfaceA for MyObj {
#[field]
async fn value_a(&self) -> i32 {
1
}
}
// Maybe it would go on both?
#[async_graphql::Interface]
impl InterfaceB for MyObj {
#[field]
async fn value_b(&self) -> i32 {
2
}
}
pub struct QueryRoot;
#[async_graphql::Object]
impl QueryRoot {
#[field]
async fn my_objs(&self, _ctx: &Context<'_>) -> impl InterfaceA + impl InterfaceB {
(MyObj {}).into()
}
}
I'm not sure if this is possible with Rust macros because I don't understand them enough.
(I added an sketch of this API at https://github.com/phated/async-graphql-interfaces/blob/master/src/ideal.rs)
from async-graphql.
This seems like a pretty good design, but unfortunately it cannot be implemented due to the limitations of the rust procedural macros. The current interface is defined in a way that I've thought about for a long time, is easy to use and easy to understand, and more importantly is rustfmt friendly. See how juniper defines the interface. It's similar to what you want, but not easy to use.
from async-graphql.
Thank you, I was just going to write that. I believe it is a requirement by GraphQL spec.
This is a common pattern when using Relay because their client adds the Node fragment onto every query.
Juniper doesn't support this as far as I can tell, which was the reason I found your awesome library.
from async-graphql.
Is it something like that?
interface Node {
id: ID!
}
interface Resource implements Node {
id: ID!
url: String
}
interface Image implements Resource & Node {
id: ID!
url: String
thumbnail: String
}
from async-graphql.
Why not just return MyObj
?
#[async_graphql::Object]
impl QueryRoot {
#[field]
async fn my_objs(&self, _ctx: &Context<'_>) -> MyObj{
MyObj {}
}
}
from async-graphql.
Each interface doesn't need to implement the others in a chain. See https://spec.graphql.org/draft/#example-ab5e5
from async-graphql.
MyObj isn't the only struct implementing the interface, I was trying to shrink the example.
from async-graphql.
Does GraphQL support such a field type?
The type of the Query {
myObj: InterfaceA & InterfaceB
}
from async-graphql.
I believe each would need to be an object that implements each interface. The interface values seem to be attached to the type declaration.
from async-graphql.
Async-graphql
currently does not support interface implementing interface.
Is the following function what you want?
MyObj
implements InterfaceB
, and because InterfaceB
implements InterfaceA
, MyObj
automatically implements InterfaceA
.
struct MyObj;
#[async_graphql::Object]
impl MyObj {
#[field]
async fn value_a(&self) -> i32 {
1
}
#[field]
async fn value_b(&self) -> i32 {
2
}
#[field]
async fn value_c(&self) -> i32 {
3
}
}
#[async_graphql::Interface(field(name = "value_a", type = "i32"))]
struct InterfaceA;
#[async_graphql::Interface(field(name = "value_b", type = "i32"), implements = "InterfaceA")]
struct InterfaceB(MyObj);
struct Query;
#[Object]
impl Query {
#[field]
async fn my_obj(&self) -> InterfaceB {
MyObj.into()
}
}
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
let query = format!(
r#"{{
myObj {{
... on InterfaceA {{
valueA
}}
... on InterfaceB {{
valueB
}}
... on MyObj {{
valueC
}}
}}
}}"#
);
assert_eq!(
schema.execute(&query).await.unwrap().data,
serde_json::json!({
"myObj": {
"valueA": 1,
"valueB": 2,
"valueC": 3,
}
})
);
from async-graphql.
I believe that would solve my current problem, yes.
from async-graphql.
It seems to be working! Thank you so much ๐
I will keep testing it on my project and file anything I find.
from async-graphql.
The last time the solution is not good, I think because I'm not support http://spec.graphql.org/draft/#sec-Interfaces.Interfaces-Implementing-Interfaces
(Draft), but in fact is another bug.
I fixed this bug in version 1.9.8
and removed the implements
attribute on the async_graphql::Interface
.
Below is the updated test, which requires manual registration because InterfaceA
is not directly referenced by the Schema
.
https://github.com/sunli829/async-graphql/blob/73aef368dfe2eb046f6d7c012f2576e19a002724/tests/interface.rs#L98
from async-graphql.
Related Issues (20)
- Access the value of "variable" arguments (`Value::Variable`)
- Has anyone does any benchmarks because im getting extremely poor results and I do not know why? HOT 8
- Get mutable referenece to the global data defined in the `Context` or `Schema` HOT 1
- Confusing `unused_mut` warning in `#[Object]` HOT 8
- How to handle both directions of one-to-many relation in federated graph
- Question: How to get server to send ping messages on subscriptions? HOT 2
- Parsing multiple operations in a file HOT 1
- Non nullable variables should allow default values HOT 3
- Object with single skipped field but with ComplexObject HOT 2
- As using proxy type
- Using flatten inside an impl with no other fields causes a compile error
- Subscription with MPSC receiver in context data
- Reduce clippy noise from #[Object] macro HOT 2
- Guard trait lifetime HOT 1
- Using generics with both SimpleObject and InputObject as field in output type fails HOT 1
- Subscription Authentication
- Stack overflow after upgrade to 7.0.2 HOT 3
- Does async-graphql validate responses?
- Error reading data from ExtensionContext after upgrade to 7.0.3
- Create a general error formateer
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ๐๐๐
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from async-graphql.