extern crate core;
pub mod auth;
mod db;
use async_graphql::{ObjectType, Schema, SubscriptionType};
use async_graphql_poem::GraphQLRequest;
use async_graphql_poem::GraphQLResponse;
use async_trait::async_trait;
use poem::{Endpoint, EndpointExt};
use sqlx::PgPool;
use crate::auth::MaybeCurrentUserMiddleware;
use crate::db::create_db_client;
use poem::FromRequest;
use poem::Request;
use poem::{listener::TcpListener, post, Route, Server};
pub use log;
pub use sqlx;
pub async fn start_graphql_server<Query, Mutation, Subscription, RequestTransformer>(
port: usize,
query: Query,
mutation: Mutation,
subscription: Subscription,
request_transformer: RequestTransformer,
) where
Query: ObjectType + Default + 'static,
Mutation: ObjectType + Default + 'static,
Subscription: SubscriptionType + Default + 'static,
RequestTransformer: FnMut(Request, async_graphql::Request) -> async_graphql::Request
+ Send
+ Sync
+ Clone
+ 'static,
{
env_logger::init();
let schema = Schema::build(query, mutation, subscription)
.enable_federation()
.finish();
let pg_pool = create_db_client().await;
let app = Route::new()
.at(
"/graphql",
post(IndexEndpoint {
schema,
request_transformer,
}),
)
.with(MaybeCurrentUserMiddleware {
pg_pool: pg_pool.clone(),
})
.data::<PgPool>(pg_pool);
Server::new(TcpListener::bind(format!("0.0.0.0:{}", port)))
.run(app)
.await
.unwrap();
}
struct IndexEndpoint<Query, Mutation, Subscription, RequestTransformer>
where
Query: ObjectType + Default + 'static,
Mutation: ObjectType + Default + 'static,
Subscription: SubscriptionType + Default + 'static,
RequestTransformer: FnMut(Request, async_graphql::Request) -> async_graphql::Request
+ Send
+ Sync
+ Clone
+ 'static,
{
pub schema: Schema<Query, Mutation, Subscription>,
pub request_transformer: RequestTransformer,
}
#[async_trait]
impl<Query, Mutation, Subscription, RequestTransformer> Endpoint
for IndexEndpoint<Query, Mutation, Subscription, RequestTransformer>
where
Query: ObjectType + Default + 'static,
Mutation: ObjectType + Default + 'static,
Subscription: SubscriptionType + Default + 'static,
RequestTransformer: FnMut(Request, async_graphql::Request) -> async_graphql::Request
+ Send
+ Sync
+ Clone
+ 'static,
{
type Output = GraphQLResponse;
async fn call(&self, req: Request) -> poem::Result<Self::Output> {
let (req, mut request_body) = req.split();
let graphql_request = GraphQLRequest::from_request(&req, &mut request_body)
.await
.unwrap();
let graphql_request = graphql_request.0;
Ok(self
.schema
.execute((self.request_transformer.clone())(req, graphql_request))
.await
.into())
}
}