Skip to content

Commit

Permalink
Axum overhaul + errors runtime + back compat
Browse files Browse the repository at this point in the history
  • Loading branch information
oscartbeaumont committed Jul 18, 2024
1 parent aaf9601 commit 5042952
Show file tree
Hide file tree
Showing 20 changed files with 562 additions and 171 deletions.
30 changes: 25 additions & 5 deletions examples/axum/src/api.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use std::{error, marker::PhantomData, path::PathBuf, sync::Arc};
use std::{marker::PhantomData, path::PathBuf, sync::Arc};

use rspc::{
procedure::{Procedure, ProcedureBuilder, ProcedureKind, ResolverInput, ResolverOutput},
procedure::{Procedure, ProcedureBuilder, ResolverInput, ResolverOutput},
Infallible,
};
use serde::Serialize;
use specta::Type;
use specta_typescript::Typescript;
use specta_util::TypeCollection;
use thiserror::Error;
Expand All @@ -12,8 +14,13 @@ pub(crate) mod chat;
pub(crate) mod invalidation;
pub(crate) mod store;

#[derive(Debug, Error)]
pub enum Error {}
#[derive(Debug, Error, Serialize, Type)]
pub enum Error {
#[error("you made a mistake: {0}")]
Mistake(String),
}

impl rspc::Error for Error {}

// `Clone` is only required for usage with Websockets
#[derive(Clone)]
Expand All @@ -31,7 +38,7 @@ pub struct BaseProcedure<TErr = Error>(PhantomData<TErr>);
impl<TErr> BaseProcedure<TErr> {
pub fn builder<TInput, TResult>() -> ProcedureBuilder<TErr, Context, Context, TInput, TResult>
where
TErr: error::Error + Send + 'static,
TErr: rspc::Error,
TInput: ResolverInput,
TResult: ResolverOutput<TErr>,
{
Expand All @@ -44,6 +51,19 @@ pub fn mount() -> Router {
.procedure("version", {
<BaseProcedure>::builder().query(|_, _: ()| async { Ok(env!("CARGO_PKG_VERSION")) })
})
.procedure("error", {
#[derive(Debug, serde::Serialize, Type)]
#[serde(tag = "type")]
enum Testing {
A(String),
}

<BaseProcedure>::builder().query(|_, _: ()| async { Ok(Testing::A("go away".into())) })
})
.procedure("error2", {
<BaseProcedure>::builder()
.query(|_, _: ()| async { Err::<(), _>(Error::Mistake("skill issue".into())) })
})
.merge("chat", chat::mount())
.merge("store", store::mount())
// TODO: I dislike this API
Expand Down
2 changes: 1 addition & 1 deletion examples/axum/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ async fn main() {
.route("/", get(|| async { "Hello, World!" }))
.nest(
"/rspc",
rspc_axum::Endpoint::new(router.clone(), ctx_fn.clone()).build(),
rspc_axum::Endpoint::new(router.clone(), ctx_fn.clone()),
)
.nest("/", rspc_openapi::mount(router, ctx_fn));

Expand Down
1 change: 1 addition & 0 deletions integrations/axum/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ categories = ["web-programming", "asynchronous"]
[features]
default = []
ws = ["dep:tokio", "axum/ws"]
file = ["dep:tokio"]

[dependencies]
rspc = { version = "0.3.0", path = "../../rspc" }
Expand Down
66 changes: 66 additions & 0 deletions integrations/axum/src/ctx_fn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use axum::{extract::FromRequestParts, http::request::Parts};
use std::{future::Future, marker::PhantomData};

// TODO: Sealed?
pub trait ContextFunction<TCtx, TState, TMarker>: Clone + Send + Sync + 'static
where
TState: Send + Sync,
TCtx: Send + 'static,
{
// fn exec(&self, parts: Parts, state: &TState) -> impl Future<Output = Result<TCtx, ()>> + Send;
}

pub struct ZeroArgMarker;
impl<TCtx, TFunc, TState> ContextFunction<TCtx, TState, ZeroArgMarker> for TFunc
where
TFunc: Fn() -> TCtx + Clone + Send + Sync + 'static,
TState: Send + Sync,
TCtx: Send + 'static,
{
// async fn exec(&self, _: Parts, _: &TState) -> Result<TCtx, ()> {
// Ok(self.clone()())
// }
}

macro_rules! impl_fn {
($marker:ident; $($generics:ident),*) => {
#[allow(unused_parens)]
pub struct $marker<$($generics),*>(PhantomData<($($generics),*)>);

impl<TCtx, TFunc, TState, $($generics: FromRequestParts<TState> + Send),*> ContextFunction<TCtx, TState, $marker<$($generics),*>> for TFunc
where
TFunc: Fn($($generics),*) -> TCtx + Clone + Send + Sync + 'static,
TState: Send + Sync,
TCtx: Send + 'static
{
// async fn exec(&self, mut parts: Parts, state: &TState) -> Result<TCtx, ExecError>
// {
// $(
// #[allow(non_snake_case)]
// let Ok($generics) = $generics::from_request_parts(&mut parts, &state).await else {
// return Err(ExecError::AxumExtractorError)
// };
// )*

// Ok(self.clone()($($generics),*))
// }
}
};
}

impl_fn!(OneArgMarker; T1);
impl_fn!(TwoArgMarker; T1, T2);
impl_fn!(ThreeArgMarker; T1, T2, T3);
impl_fn!(FourArgMarker; T1, T2, T3, T4);
impl_fn!(FiveArgMarker; T1, T2, T3, T4, T5);
impl_fn!(SixArgMarker; T1, T2, T3, T4, T5, T6);
impl_fn!(SevenArgMarker; T1, T2, T3, T4, T5, T6, T7);
impl_fn!(EightArgMarker; T1, T2, T3, T4, T5, T6, T7, T8);
impl_fn!(NineArgMarker; T1, T2, T3, T4, T5, T6, T7, T8, T9);
impl_fn!(TenArgMarker; T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
impl_fn!(ElevenArgMarker; T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
impl_fn!(TwelveArgMarker; T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
impl_fn!(ThirteenArgMarker; T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
impl_fn!(FourteenArgMarker; T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
impl_fn!(FifteenArgMarker; T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15);
impl_fn!(SixteenArgMarker; T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16);
Loading

0 comments on commit 5042952

Please sign in to comment.