-
Notifications
You must be signed in to change notification settings - Fork 8
Open
Description
I would like if qubit handled Results
for me.
I'm using a database for the queries and every operation returns a Result.
I would like if qubit:
- Did not send the Err contents to the client-side
- Had a compile time setting that forced every handler to return a QubitResult
- Had an option on the client to throw on Errs, generates types for the successful Ok only
For now I'm using a custom result type:
use std::error::Error;
use std::sync::Arc;
use serde::Serialize;
use ts_rs::TS;
#[derive(Debug, Clone)]
pub enum RpcErrorMessage {
Anyhow(Arc<anyhow::Error>),
Public(String),
}
impl Serialize for RpcErrorMessage {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let msg = match self {
RpcErrorMessage::Anyhow(e) => {
dbg!(e);
"Internal Server Error"
}
RpcErrorMessage::Public(s) => s,
};
serializer.serialize_str(msg)
}
}
#[derive(Debug, Clone, Serialize, TS)]
pub struct RpcError {
#[ts(as = "String")]
message: RpcErrorMessage,
}
fn app_anyhow<T: Error + Send + Sync + 'static>(it: T) -> RpcError {
RpcError {
message: RpcErrorMessage::Anyhow(Arc::new(anyhow::Error::new(it))),
}
}
impl<T: Error + Send + Sync + 'static> From<T> for RpcError {
fn from(value: T) -> Self {
app_anyhow(value)
}
}
pub fn public_err<T>(msg: &str) -> Result<T, RpcError> {
Err(RpcError {
message: RpcErrorMessage::Public(msg.to_string()),
})
}
pub type RpcResult<T> = Result<T, RpcError>;
Usage:
#[handler(query)]
async fn read_posts(ctx: AuthCtx) -> RpcResult<Vec<Post>> {
use crate::schema::posts::dsl::*;
let results = posts
.limit(5)
.select(Post::as_select())
.load(&mut ctx.pg_pool.get()?)?;
Ok(results)
}
And an unwrap function in TS
type AnyResult = { Ok: any } | { Err: { message: string } };
type ExtractOk<T extends AnyResult> = T extends { Ok: infer U } ? U : never;
export const Unwrap = <T extends AnyResult>(x: T): ExtractOk<T> => {
if ("Ok" in x) {
return x.Ok;
}
if ("Err" in x) {
if ("message" in x.Err) {
throw new Error(x.Err.message);
}
}
console.log(x);
throw new Error("Unwrap failed: " + String(x));
};
Thanks!
epatters, nicolai0, akx and GRA0007
Metadata
Metadata
Assignees
Labels
No labels