raphtory-graphql 0.17.0

Raphtory GraphQL server
use crate::model::plugins::mutation_plugin::MutationPlugin;
use async_graphql::{
    dynamic::{Field, FieldFuture, FieldValue, InputValue, Object, ResolverContext, TypeRef},
    FieldResult,
};
use dynamic_graphql::internal::{Register, Registry};
use futures_util::future::BoxFuture;

use super::query_plugin::QueryPlugin;

pub trait Operation<'a, A: Send + Sync + 'static> {
    type OutputType: Register + 'static;

    fn output_type() -> TypeRef;

    fn args<'b>() -> Vec<(&'b str, TypeRef)>;

    fn apply<'b>(
        entry_point: &A,
        ctx: ResolverContext,
    ) -> BoxFuture<'b, FieldResult<Option<FieldValue<'b>>>>;

    fn register_operation(name: &str, registry: Registry, parent: Object) -> (Registry, Object) {
        let registry = registry.register::<Self::OutputType>();
        let mut field = Field::new(name, Self::output_type(), |ctx| {
            FieldFuture::new(async move {
                let entry_point: &A = ctx.parent_value.downcast_ref().unwrap();
                Self::apply(&entry_point, ctx).await
            })
        });

        for (name, type_ref) in Self::args() {
            field = field.argument(InputValue::new(name, type_ref));
        }
        let parent = parent.field(field);
        (registry, parent)
    }
}

pub(crate) struct NoOpMutation;

impl<'a> Operation<'a, MutationPlugin> for NoOpMutation {
    type OutputType = String;

    fn output_type() -> TypeRef {
        TypeRef::named_nn(TypeRef::STRING)
    }

    fn args<'b>() -> Vec<(&'b str, TypeRef)> {
        vec![]
    }

    fn apply<'b>(
        _entry_point: &MutationPlugin,
        _ctx: ResolverContext,
    ) -> BoxFuture<'b, FieldResult<Option<FieldValue<'b>>>> {
        Box::pin(async move { Ok(Some(FieldValue::value("no-op".to_owned()))) })
    }
}

pub(crate) struct NoOpQuery;

impl<'a> Operation<'a, QueryPlugin> for NoOpQuery {
    type OutputType = String;

    fn output_type() -> TypeRef {
        TypeRef::named_nn(TypeRef::STRING)
    }

    fn args<'b>() -> Vec<(&'b str, TypeRef)> {
        vec![]
    }

    fn apply<'b>(
        _entry_point: &QueryPlugin,
        _ctx: ResolverContext,
    ) -> BoxFuture<'b, FieldResult<Option<FieldValue<'b>>>> {
        Box::pin(async move { Ok(Some(FieldValue::value("no-op".to_owned()))) })
    }
}