Skip to content

Releases: async-graphql/async-graphql

5.0

28 Nov 06:30
Compare
Choose a tag to compare
  • Add support for dynamic schema
  • Add support to federation(v2) for dynamic schema
  • Add tempfile feature, enabled by default
  • Keep object 'implements' order stable in SDL export #1142
  • Fix regression on ComplexObject descriptions #1141
  • Fixes #1138
  • Fixes #1140

4.0

17 May 00:53
Compare
Choose a tag to compare
4.0
  • Implement the ConnectionNameType and EdgeNameType traits to specify GraphQL type names for Connection and Edge, which can be automatically generated using DefaultConnectionName and DefaultEdgeName.
  • Add #[non_exhaustive] attribute to Request/Response types.
  • Introduce ability to pre-parse Request's query. #891
  • Add introspection-only mode. #894
  • Add bson-uuid feature to implement ScalarType for bson::Uuid. #875
  • Bump regex crate from 1.4.5 to 1.5.5. #862
  • Bump chrono-tz crate from 0.5.3 to 0.6.1. #831
  • Move the pest parser code generation step into a test. #901
  • Update log to version 0.4.16. #903
  • Added impl of CursorType for floats #897
  • Implement OutputType for tokio::sync::RwLock and tokio::sync::Mutex. #896
  • Bump uuid to 1.0.0. #907
  • Add some options for exporting SDL. #877
  • Cache parsed ExecuteDocument in APQ. #919
  • Fixed OneofObject restriction on inner types being unique. #923

3.0

19 Nov 00:19
Compare
Choose a tag to compare
3.0

Changes in v3.0:

Use the SimpleObject macro and the InputObject macro at the same time.

#[derive(SimpleObject, InputObject)]
#[graphql(input_name = "MyObjectInput")]
struct MyObject {
    #[graphql(default = 10)]
    a: i32,
    b: bool,
}

Types that are not referenced will be hidden in introspection.

#[derive(SimpleObject)]
struct MyObj {
    a: i32,
}

#[Object]
struct Query {
    #[graphql(visible = false)]
    fn obj(&self) -> MyObj {
        todo!()
    }
}

let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
assert_eq!(
    schema.execute(r#"{ __type(name: "MyObj") { name } }"#).await.into_result().unwrap().data,
    value!({ "__type": null })
);

Make the API of integrations is more consistent.

Remove async-graphql-tide.

Rework validators.

Built-in validator:

struct Query;

#[Object]
impl Query {
    async fn value1(&self, #[graphql(validator(maximum = 10))] n: i32) -> i32 {
        n
    }
}

Custom-validator:

struct MyValidator {
    expect: i32,
}

impl MyValidator {
    pub fn new(n: i32) -> Self {
        MyValidator { expect: n }
    }
}

impl CustomValidator<i32> for MyValidator {
    fn check(&self, value: &i32) -> Result<(), String> {
        if *value == self.expect {
            Ok(())
        } else {
            Err(format!("expect 100, actual {}", value))
        }
    }
}

struct Query;

#[Object]
impl Query {
    async fn value(
        &self,
        #[graphql(validator(custom = "MyValidator::new(100)"))] n: i32,
    ) -> i32 {
        n
    }
}

Rework guards.

#[derive(Eq, PartialEq, Copy, Clone)]
enum Role {
    Admin,
    Guest,
}

pub struct RoleGuard {
    role: Role,
}

impl RoleGuard {
    fn new(role: Role) -> Self {
        Self { role }
    }
}

#[async_trait::async_trait]
impl Guard for RoleGuard {
    async fn check(&self, ctx: &Context<'_>) -> Result<()> {
        if ctx.data_opt::<Role>() == Some(&self.role) {
            Ok(())
        } else {
            Err("Forbidden".into())
        }
    }
}

 #[derive(SimpleObject)]
struct Query {
    #[graphql(guard = "RoleGuard::new(Role::Admin)")]
    value: i32,
}

Use parameters:

struct EqGuard {
    expect: i32,
    actual: i32,
}

impl EqGuard {
    fn new(expect: i32, actual: i32) -> Self {
        Self { expect, actual }
    }
}

#[async_trait::async_trait]
impl Guard for EqGuard {
    async fn check(&self, _ctx: &Context<'_>) -> Result<()> {
        if self.expect != self.actual {
            Err("Forbidden".into())
        } else {
            Ok(())
        }
    }
}

struct Query;

#[Object]
impl Query {
    #[graphql(guard = "EqGuard::new(100, value)")]
    async fn get(&self, value: i32) -> i32 {
        value
    }
}