carbon-core 1.0.0

Core library for Carbon
Documentation
//! Pre-wired Juniper + Axum integration. Build a schema with
//! [`build_schema`], turn it into a [`graphql_router`] mounted on
//! `/graphql` (GET + POST) and `/graphiql` (playground), then merge
//! into your Axum app.

use {
    axum::{
        routing::{get, on, MethodFilter},
        Extension, Router,
    },
    juniper::{EmptyMutation, EmptySubscription, RootNode},
    juniper_axum::{extract::JuniperRequest, graphiql, response::JuniperResponse},
    std::sync::Arc,
};

pub type DefaultMutation<C> = EmptyMutation<C>;
pub type DefaultSubscription<C> = EmptySubscription<C>;

pub fn build_schema<Q, C>(
    query_root: Q,
) -> Arc<RootNode<'static, Q, DefaultMutation<C>, DefaultSubscription<C>>>
where
    Q: juniper::GraphQLType<Context = C, TypeInfo = ()> + Send + Sync + 'static,
    C: juniper::Context + Send + Sync + 'static,
{
    Arc::new(RootNode::new(
        query_root,
        DefaultMutation::new(),
        DefaultSubscription::new(),
    ))
}

type ExtensionSchema<Q, C> =
    Extension<Arc<RootNode<'static, Q, DefaultMutation<C>, DefaultSubscription<C>>>>;

pub fn graphql_router<Q, C>(
    schema: Arc<RootNode<'static, Q, DefaultMutation<C>, DefaultSubscription<C>>>,
    context: C,
) -> Router
where
    Q: juniper::GraphQLTypeAsync<Context = C, TypeInfo = ()>
        + juniper::GraphQLValueAsync<Context = C, TypeInfo = ()>
        + Send
        + Sync
        + 'static,
    C: juniper::Context + Clone + Send + Sync + 'static,
{
    async fn handler<Q, C>(
        Extension(schema): ExtensionSchema<Q, C>,
        Extension(ctx): Extension<C>,
        juniper_axum::extract::JuniperRequest(req): JuniperRequest<juniper::DefaultScalarValue>,
    ) -> JuniperResponse<juniper::DefaultScalarValue>
    where
        Q: juniper::GraphQLTypeAsync<Context = C, TypeInfo = ()> + Send + Sync + 'static,
        C: juniper::Context + Clone + Send + Sync + 'static,
    {
        JuniperResponse(req.execute(&schema, &ctx).await)
    }

    Router::new()
        .route(
            "/graphql",
            on(MethodFilter::GET.or(MethodFilter::POST), handler::<Q, C>),
        )
        .route("/graphiql", get(graphiql("/graphql", None)))
        .layer(Extension(schema))
        .layer(Extension(context))
}