use async_graphql::Schema;
pub struct ProgrammaticSchemaBuilder<Q, M, S> {
query: Option<Q>,
mutation: Option<M>,
subscription: Option<S>,
services: Vec<Box<dyn std::any::Any + Send + Sync>>,
}
impl<Q, M, S> ProgrammaticSchemaBuilder<Q, M, S>
where
Q: async_graphql::ObjectType + 'static,
M: async_graphql::ObjectType + 'static,
S: async_graphql::SubscriptionType + 'static,
{
pub fn new() -> Self {
Self {
query: None,
mutation: None,
subscription: None,
services: Vec::new(),
}
}
pub fn query(mut self, query: Q) -> Self {
self.query = Some(query);
self
}
pub fn mutation(mut self, mutation: M) -> Self {
self.mutation = Some(mutation);
self
}
pub fn subscription(mut self, subscription: S) -> Self {
self.subscription = Some(subscription);
self
}
pub fn add_service<T: Send + Sync + 'static>(mut self, service: T) -> Self {
self.services.push(Box::new(service));
self
}
pub fn build(self) -> Schema<Q, M, S> {
let query = self.query.expect("Query root is required");
let mutation = self.mutation.expect("Mutation root is required");
let subscription = self.subscription.expect("Subscription root is required");
let mut schema_builder = Schema::build(query, mutation, subscription);
for service in self.services {
schema_builder = schema_builder.data(service);
}
schema_builder.finish()
}
}
impl<Q, M, S> Default for ProgrammaticSchemaBuilder<Q, M, S>
where
Q: async_graphql::ObjectType + 'static,
M: async_graphql::ObjectType + 'static,
S: async_graphql::SubscriptionType + 'static,
{
fn default() -> Self {
Self::new()
}
}
#[derive(Default)]
pub struct EmptyQuery;
#[async_graphql::Object]
impl EmptyQuery {
async fn _empty(&self) -> &str {
""
}
}
#[derive(Default)]
pub struct EmptyMutation;
#[async_graphql::Object]
impl EmptyMutation {
async fn _empty(&self) -> &str {
""
}
}
#[derive(Default)]
pub struct EmptySubscription;
#[async_graphql::Subscription]
impl EmptySubscription {
async fn _empty(&self) -> impl async_graphql::futures_util::Stream<Item = &str> {
async_graphql::futures_util::stream::empty()
}
}
#[macro_export]
macro_rules! merge_resolvers {
($($resolver:ty),+ $(,)?) => {
{
use async_graphql::MergedObject;
#[derive(MergedObject, Default)]
struct MergedRoot($($resolver),+);
MergedRoot::default()
}
};
}
pub fn create_merged_schema<Q, M, S>(
_query_resolvers: Vec<Q>,
_mutation_resolvers: Vec<M>,
_subscription_resolvers: Vec<S>,
) -> ProgrammaticSchemaBuilder<Q, M, S>
where
Q: async_graphql::ObjectType + 'static,
M: async_graphql::ObjectType + 'static,
S: async_graphql::SubscriptionType + 'static,
{
ProgrammaticSchemaBuilder::new()
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Default)]
struct TestQuery;
#[async_graphql::Object]
impl TestQuery {
async fn test(&self) -> &str {
"test"
}
}
#[test]
fn test_schema_builder() {
let _schema = ProgrammaticSchemaBuilder::new()
.query(TestQuery)
.mutation(EmptyMutation)
.subscription(EmptySubscription)
.build();
}
}