Created
December 22, 2021 10:24
-
-
Save oscartbeaumont/8e03041c021d9a22de2b15edee9308ea to your computer and use it in GitHub Desktop.
Async GraphQL Generic Interface Bug
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "async-graphql-relay-example" | |
version = "0.1.0" | |
authors = ["Oscar Beaumont <[email protected]>"] | |
edition = "2018" | |
[dependencies] | |
async-graphql = "3.0.17" | |
actix-web = "4.0.0-beta.14" | |
async-graphql-actix-web = "3.0.17" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
query { | |
user { | |
id | |
name | |
} | |
tenant { | |
id | |
name | |
} | |
} | |
query { | |
node(id: "92ba0c2d4b4e4e2991dd8f96a078c3ffu") { | |
id | |
... on User { | |
name | |
role | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Invalid schema Error:\nInterface field Node.id expects type NonGenericID! but Tenant.id is type GenericID!.\nInterface field Node.id expects type NonGenericID! but User.id is type GenericID!. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use crate::tenant::Tenant; | |
use crate::user::User; | |
use actix_web::guard; | |
use actix_web::web::Data; | |
use actix_web::{web, App, HttpResponse, HttpServer, Responder}; | |
use async_graphql::http::{playground_source, GraphQLPlaygroundConfig}; | |
use async_graphql::{EmptyMutation, EmptySubscription, Interface, Object}; | |
use async_graphql_actix_web::{GraphQLRequest, GraphQLResponse}; | |
use test::{GenericID, NonGenericID}; | |
mod tenant; | |
mod test; | |
mod user; | |
pub struct QueryRoot; | |
#[derive(Interface)] | |
#[graphql(field(name = "id", type = "NonGenericID"))] | |
pub enum Node { | |
User(User), | |
Tenant(Tenant), | |
} | |
#[Object] | |
impl QueryRoot { | |
async fn user(&self) -> User { | |
User { | |
id: GenericID::new("user_one".into()), | |
name: "Oscar".to_string(), | |
role: "Testing123".to_string(), | |
} | |
} | |
async fn tenant(&self) -> Tenant { | |
Tenant { | |
id: GenericID::new("tenant_one".into()), | |
name: "My Company".to_string(), | |
description: "Testing123".to_string(), | |
} | |
} | |
async fn node(&self, _id: String) -> Node { | |
// This only even returns a user which is useless but refer to the Relay server specification for how this query should work. | |
User { | |
id: GenericID::new("user_one".into()), | |
name: "Oscar".to_string(), | |
role: "Testing123".to_string(), | |
} | |
.into() | |
} | |
} | |
pub type Schema = async_graphql::Schema<QueryRoot, EmptyMutation, EmptySubscription>; | |
pub async fn handler(schema: web::Data<Schema>, req: GraphQLRequest) -> GraphQLResponse { | |
schema.execute(req.into_inner()).await.into() | |
} | |
pub async fn playground() -> impl Responder { | |
HttpResponse::Ok() | |
.content_type("text/html; charset=utf-8") | |
.body(playground_source(GraphQLPlaygroundConfig::new("/"))) | |
} | |
#[actix_web::main] | |
async fn main() -> std::io::Result<()> { | |
let schema = Schema::build(QueryRoot, EmptyMutation, EmptySubscription).finish(); | |
println!("Listening http://localhost:8080/ ..."); | |
HttpServer::new(move || { | |
App::new() | |
.app_data(Data::new(schema.clone())) | |
.service(web::resource("/").guard(guard::Post()).to(handler)) | |
.service(web::resource("/").guard(guard::Get()).to(playground)) | |
}) | |
.bind(("0.0.0.0", 8080))? | |
.run() | |
.await | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use async_graphql::SimpleObject; | |
use crate::test::GenericID; | |
#[derive(Debug, SimpleObject)] | |
pub struct Tenant { | |
pub id: GenericID<Self>, | |
pub name: String, | |
pub description: String, | |
} | |
impl ToString for Tenant { | |
fn to_string(&self) -> String { | |
format!("{}", self.name) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::marker::PhantomData; | |
use async_graphql::{InputValueResult, Scalar, ScalarType, Value}; | |
use crate::{tenant::Tenant, user::User}; | |
#[derive(Debug)] | |
pub struct GenericID<T: ToString>(String, PhantomData<T>); | |
impl<T: ToString> GenericID<T> { | |
pub fn new(val: String) -> Self { | |
return GenericID(val, PhantomData); | |
} | |
} | |
#[Scalar] | |
impl<T: ToString + Send + Sync> ScalarType for GenericID<T> { | |
fn parse(_value: Value) -> InputValueResult<Self> { | |
unimplemented!(); | |
} | |
fn to_value(&self) -> Value { | |
Value::String(String::from(self.0.clone())) | |
} | |
} | |
#[derive(Debug)] | |
pub struct NonGenericID(String); | |
impl From<&GenericID<User>> for NonGenericID { | |
fn from(t: &GenericID<User>) -> Self { | |
NonGenericID(String::from(t.0.clone())) | |
} | |
} | |
impl From<&GenericID<Tenant>> for NonGenericID { | |
fn from(t: &GenericID<Tenant>) -> Self { | |
NonGenericID(String::from(t.0.clone())) | |
} | |
} | |
#[Scalar] | |
impl ScalarType for NonGenericID { | |
fn parse(_value: async_graphql::Value) -> async_graphql::InputValueResult<Self> { | |
panic!("not implemented"); | |
} | |
fn to_value(&self) -> async_graphql::Value { | |
Value::String(self.0.clone()) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use async_graphql::SimpleObject; | |
use crate::test::GenericID; | |
#[derive(Debug, SimpleObject)] | |
pub struct User { | |
pub id: GenericID<Self>, | |
pub name: String, | |
pub role: String, | |
} | |
impl ToString for User { | |
fn to_string(&self) -> String { | |
format!("{}", self.name) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment