This commit is contained in:
Aiden McClelland
2025-11-07 00:35:18 -07:00
parent 068db905ee
commit 9d75ab4610
7 changed files with 634 additions and 367 deletions

681
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,7 @@ repository = "https://github.com/Start9Labs/rpc-toolkit"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
cbor = ["serde_cbor"]
default = []
default = ["cbor", "ts-rs"]
[dependencies]
axum = "0.8"
@@ -37,5 +37,6 @@ serde_json = "1.0"
thiserror = "2.0"
tokio = { version = "1", features = ["full"] }
tokio-stream = { version = "0.1", features = ["io-util", "net"] }
ts-rs = { version = "9.0.1", optional = true }
url = "2"
yajrc = "0.1"

View File

@@ -209,6 +209,21 @@ where
type Err = RemoteHandler::Err;
}
#[cfg(feature = "ts-rs")]
impl<Context, RemoteContext, RemoteHandler, Extra> crate::handler::HandlerTS
for CallRemoteHandler<Context, RemoteContext, RemoteHandler, Extra>
where
RemoteHandler: crate::handler::HandlerTS,
Extra: Send + Sync + 'static,
{
fn params_ty(&self) -> Option<String> {
self.handler.params_ty()
}
fn return_ty(&self) -> Option<String> {
self.handler.return_ty()
}
}
impl<Context, RemoteContext, RemoteHandler, Extra> HandlerFor<Context>
for CallRemoteHandler<Context, RemoteContext, RemoteHandler, Extra>
where

View File

@@ -117,6 +117,18 @@ impl<H: HandlerTypes> HandlerTypes for NoCli<H> {
type Ok = H::Ok;
type Err = H::Err;
}
#[cfg(feature = "ts-rs")]
impl<H> crate::handler::HandlerTS for NoCli<H>
where
H: crate::handler::HandlerTS,
{
fn params_ty(&self) -> Option<String> {
self.0.params_ty()
}
fn return_ty(&self) -> Option<String> {
self.0.return_ty()
}
}
impl<Context, H> HandlerFor<Context> for NoCli<H>
where
Context: crate::Context,
@@ -199,6 +211,18 @@ impl<H: HandlerTypes> HandlerTypes for NoDisplay<H> {
type Ok = H::Ok;
type Err = H::Err;
}
#[cfg(feature = "ts-rs")]
impl<H> crate::handler::HandlerTS for NoDisplay<H>
where
H: crate::handler::HandlerTS,
{
fn params_ty(&self) -> Option<String> {
self.0.params_ty()
}
fn return_ty(&self) -> Option<String> {
self.0.return_ty()
}
}
impl<Context, H> HandlerFor<Context> for NoDisplay<H>
where
@@ -309,6 +333,19 @@ where
type Ok = H::Ok;
type Err = H::Err;
}
#[cfg(feature = "ts-rs")]
impl<P, H> crate::handler::HandlerTS for CustomDisplay<P, H>
where
H: crate::handler::HandlerTS,
P: Send + Sync + Clone + 'static,
{
fn params_ty(&self) -> Option<String> {
self.handler.params_ty()
}
fn return_ty(&self) -> Option<String> {
self.handler.return_ty()
}
}
impl<Context, P, H> HandlerFor<Context> for CustomDisplay<P, H>
where
@@ -467,6 +504,20 @@ where
type Ok = H::Ok;
type Err = H::Err;
}
#[cfg(feature = "ts-rs")]
impl<F, H, Context> crate::handler::HandlerTS for CustomDisplayFn<F, H, Context>
where
H: crate::handler::HandlerTS,
F: Send + Sync + Clone + 'static,
Context: 'static,
{
fn params_ty(&self) -> Option<String> {
self.handler.params_ty()
}
fn return_ty(&self) -> Option<String> {
self.handler.return_ty()
}
}
impl<Context, F, H, C> HandlerFor<Context> for CustomDisplayFn<F, H, C>
where
@@ -669,6 +720,22 @@ where
type Err = H::Err;
}
#[cfg(feature = "ts-rs")]
impl<Params, InheritedParams, H, F> crate::handler::HandlerTS
for InheritanceHandler<Params, InheritedParams, H, F>
where
Params: Send + Sync + 'static,
InheritedParams: Send + Sync + 'static,
H: crate::handler::HandlerTS,
{
fn params_ty(&self) -> Option<String> {
self.handler.params_ty()
}
fn return_ty(&self) -> Option<String> {
self.handler.return_ty()
}
}
impl<Context, Params, InheritedParams, H, F> HandlerFor<Context>
for InheritanceHandler<Params, InheritedParams, H, F>
where
@@ -786,6 +853,19 @@ where
type Ok = H::Ok;
type Err = H::Err;
}
#[cfg(feature = "ts-rs")]
impl<M, H> crate::handler::HandlerTS for WithAbout<M, H>
where
H: crate::handler::HandlerTS,
M: Clone + Send + Sync + 'static,
{
fn params_ty(&self) -> Option<String> {
self.handler.params_ty()
}
fn return_ty(&self) -> Option<String> {
self.handler.return_ty()
}
}
impl<Context, M, H> HandlerFor<Context> for WithAbout<M, H>
where
Context: crate::Context,

View File

@@ -7,6 +7,8 @@ use imbl_value::imbl::OrdMap;
use imbl_value::Value;
use serde::de::DeserializeOwned;
use serde::Serialize;
#[cfg(feature = "ts-rs")]
use ts_rs::TS;
use crate::util::PhantomData;
use crate::{
@@ -42,6 +44,21 @@ impl<F, T, E, Args> std::fmt::Debug for FromFn<F, T, E, Args> {
.finish()
}
}
#[cfg(feature = "ts-rs")]
impl<F, T, E, Args> crate::handler::HandlerTS for FromFn<F, T, E, Args>
where
Self: HandlerTypes,
<Self as HandlerTypes>::Params: ts_rs::TS,
<Self as HandlerTypes>::Ok: ts_rs::TS,
{
fn params_ty(&self) -> Option<String> {
Some(<Self as HandlerTypes>::Params::inline())
}
fn return_ty(&self) -> Option<String> {
Some(<Self as HandlerTypes>::Ok::inline())
}
}
impl<Context, F, T, E, Args> PrintCliResult<Context> for FromFn<F, T, E, Args>
where
Context: crate::Context,
@@ -149,6 +166,21 @@ impl<F, Fut, T, E, Args> std::fmt::Debug for FromFnAsync<F, Fut, T, E, Args> {
f.debug_struct("FromFnAsync").finish()
}
}
#[cfg(feature = "ts-rs")]
impl<F, Fut, T, E, Args> crate::handler::HandlerTS for FromFnAsync<F, Fut, T, E, Args>
where
Self: HandlerTypes,
<Self as HandlerTypes>::Params: ts_rs::TS,
<Self as HandlerTypes>::Ok: ts_rs::TS,
{
fn params_ty(&self) -> Option<String> {
Some(<Self as HandlerTypes>::Params::inline())
}
fn return_ty(&self) -> Option<String> {
Some(<Self as HandlerTypes>::Ok::inline())
}
}
impl<Context, F, Fut, T, E, Args> PrintCliResult<Context> for FromFnAsync<F, Fut, T, E, Args>
where
Context: crate::Context,
@@ -243,6 +275,21 @@ impl<F, Fut, T, E, Args> std::fmt::Debug for FromFnAsyncLocal<F, Fut, T, E, Args
f.debug_struct("FromFnAsyncLocal").finish()
}
}
#[cfg(feature = "ts-rs")]
impl<F, Fut, T, E, Args> crate::handler::HandlerTS for FromFnAsyncLocal<F, Fut, T, E, Args>
where
Self: HandlerTypes,
<Self as HandlerTypes>::Params: ts_rs::TS,
<Self as HandlerTypes>::Ok: ts_rs::TS,
{
fn params_ty(&self) -> Option<String> {
Some(<Self as HandlerTypes>::Params::inline())
}
fn return_ty(&self) -> Option<String> {
Some(<Self as HandlerTypes>::Ok::inline())
}
}
impl<Context, F, Fut, T, E, Args> PrintCliResult<Context> for FromFnAsyncLocal<F, Fut, T, E, Args>
where
Context: crate::Context,
@@ -335,6 +382,12 @@ where
impl<F, T, E, Context, Params, InheritedParams> HandlerFor<Context>
for FromFn<F, T, E, HandlerArgs<Context, Params, InheritedParams>>
where
Self: crate::handler::HandlerRequires<
Params = Params,
InheritedParams = InheritedParams,
Ok = T,
Err = E,
>,
F: Fn(HandlerArgs<Context, Params, InheritedParams>) -> Result<T, E>
+ Send
+ Sync
@@ -386,6 +439,12 @@ where
impl<F, Fut, T, E, Context, Params, InheritedParams> HandlerFor<Context>
for FromFnAsync<F, Fut, T, E, HandlerArgs<Context, Params, InheritedParams>>
where
Self: crate::handler::HandlerRequires<
Params = Params,
InheritedParams = InheritedParams,
Ok = T,
Err = E,
>,
F: Fn(HandlerArgs<Context, Params, InheritedParams>) -> Fut + Send + Sync + Clone + 'static,
Fut: Future<Output = Result<T, E>> + Send + 'static,
T: Send + Sync + 'static,
@@ -419,6 +478,7 @@ where
impl<Context, F, T, E> HandlerFor<Context> for FromFn<F, T, E, ()>
where
Self: crate::handler::HandlerRequires<Ok = T, Err = E>,
Context: crate::Context,
F: Fn() -> Result<T, E> + Send + Sync + Clone + 'static,
T: Send + Sync + 'static,
@@ -456,6 +516,7 @@ where
impl<Context, F, Fut, T, E> HandlerFor<Context> for FromFnAsync<F, Fut, T, E, ()>
where
Self: crate::handler::HandlerRequires<Ok = T, Err = E>,
Context: crate::Context,
F: Fn() -> Fut + Send + Sync + Clone + 'static,
Fut: Future<Output = Result<T, E>> + Send + 'static,
@@ -485,6 +546,7 @@ where
impl<Context, F, T, E> HandlerFor<Context> for FromFn<F, T, E, (Context,)>
where
Self: crate::handler::HandlerRequires<Ok = T, Err = E>,
Context: crate::Context,
F: Fn(Context) -> Result<T, E> + Send + Sync + Clone + 'static,
T: Send + Sync + 'static,
@@ -526,6 +588,7 @@ where
impl<Context, F, Fut, T, E> HandlerFor<Context> for FromFnAsync<F, Fut, T, E, (Context,)>
where
Self: crate::handler::HandlerRequires<Ok = T, Err = E>,
Context: crate::Context,
F: Fn(Context) -> Fut + Send + Sync + Clone + 'static,
Fut: Future<Output = Result<T, E>> + Send + 'static,
@@ -559,6 +622,7 @@ where
impl<Context, F, T, E, Params> HandlerFor<Context> for FromFn<F, T, E, (Context, Params)>
where
Self: crate::handler::HandlerRequires<Params = Params, Ok = T, Err = E>,
Context: crate::Context,
F: Fn(Context, Params) -> Result<T, E> + Send + Sync + Clone + 'static,
Params: DeserializeOwned + Send + Sync + 'static,
@@ -606,6 +670,7 @@ where
impl<Context, F, Fut, T, E, Params> HandlerFor<Context>
for FromFnAsync<F, Fut, T, E, (Context, Params)>
where
Self: crate::handler::HandlerRequires<Params = Params, Ok = T, Err = E>,
Context: crate::Context,
F: Fn(Context, Params) -> Fut + Send + Sync + Clone + 'static,
Fut: Future<Output = Result<T, E>> + Send + 'static,
@@ -646,6 +711,7 @@ where
impl<Context, F, T, E, Params, InheritedParams> HandlerFor<Context>
for FromFn<F, T, E, (Context, Params, InheritedParams)>
where
Self: crate::handler::HandlerRequires<Params = Params, InheritedParams = InheritedParams, Ok = T, Err = E>,
Context: crate::Context,
F: Fn(Context, Params, InheritedParams) -> Result<T, E> + Send + Sync + Clone + 'static,
Params: DeserializeOwned + Send + Sync + 'static,
@@ -699,6 +765,7 @@ where
impl<Context, F, Fut, T, E, Params, InheritedParams> HandlerFor<Context>
for FromFnAsync<F, Fut, T, E, (Context, Params, InheritedParams)>
where
Self: crate::handler::HandlerRequires<Params = Params, InheritedParams = InheritedParams, Ok = T, Err = E>,
Context: crate::Context,
F: Fn(Context, Params, InheritedParams) -> Fut + Send + Sync + Clone + 'static,
Fut: Future<Output = Result<T, E>> + Send + 'static,
@@ -744,6 +811,7 @@ where
impl<F, Fut, T, E, Context, Params, InheritedParams> HandlerFor<Context>
for FromFnAsyncLocal<F, Fut, T, E, HandlerArgs<Context, Params, InheritedParams>>
where
Self: crate::handler::HandlerRequires<Params = Params, InheritedParams = InheritedParams, Ok = T, Err = E>,
F: Fn(HandlerArgs<Context, Params, InheritedParams>) -> Fut + Send + Sync + Clone + 'static,
Fut: Future<Output = Result<T, E>> + 'static,
T: Send + Sync + 'static,
@@ -760,7 +828,8 @@ where
if let Some(rt) = handle_args.context.runtime() {
local.block_on(&*rt, (self.function)(handle_args))
} else {
tokio::runtime::Handle::current().block_on(local.run_until((self.function)(handle_args)))
tokio::runtime::Handle::current()
.block_on(local.run_until((self.function)(handle_args)))
}
}
async fn handle_async(
@@ -789,6 +858,7 @@ where
impl<Context, F, Fut, T, E> HandlerFor<Context> for FromFnAsyncLocal<F, Fut, T, E, ()>
where
Self: crate::handler::HandlerRequires<Ok = T, Err = E>,
Context: crate::Context,
F: Fn() -> Fut + Send + Sync + Clone + 'static,
Fut: Future<Output = Result<T, E>> + 'static,
@@ -833,6 +903,7 @@ where
impl<Context, F, Fut, T, E> HandlerFor<Context> for FromFnAsyncLocal<F, Fut, T, E, (Context,)>
where
Self: crate::handler::HandlerRequires<Ok = T, Err = E>,
Context: crate::Context,
F: Fn(Context) -> Fut + Send + Sync + Clone + 'static,
Fut: Future<Output = Result<T, E>> + 'static,
@@ -847,7 +918,8 @@ where
if let Some(rt) = handle_args.context.runtime() {
local.block_on(&*rt, (self.function)(handle_args.context))
} else {
tokio::runtime::Handle::current().block_on(local.run_until((self.function)(handle_args.context)))
tokio::runtime::Handle::current()
.block_on(local.run_until((self.function)(handle_args.context)))
}
}
async fn handle_async(
@@ -861,7 +933,8 @@ where
}
}
impl<Context, F, Fut, T, E, Params> HandlerTypes for FromFnAsyncLocal<F, Fut, T, E, (Context, Params)>
impl<Context, F, Fut, T, E, Params> HandlerTypes
for FromFnAsyncLocal<F, Fut, T, E, (Context, Params)>
where
Context: crate::Context,
F: Fn(Context, Params) -> Fut + Send + Sync + Clone + 'static,
@@ -879,6 +952,7 @@ where
impl<Context, F, Fut, T, E, Params> HandlerFor<Context>
for FromFnAsyncLocal<F, Fut, T, E, (Context, Params)>
where
Self: crate::handler::HandlerRequires<Params = Params, Ok = T, Err = E>,
Context: crate::Context,
F: Fn(Context, Params) -> Fut + Send + Sync + Clone + 'static,
Fut: Future<Output = Result<T, E>> + 'static,
@@ -892,9 +966,13 @@ where
) -> Result<Self::Ok, Self::Err> {
let local = tokio::task::LocalSet::new();
if let Some(rt) = handle_args.context.runtime() {
local.block_on(&*rt, (self.function)(handle_args.context, handle_args.params))
local.block_on(
&*rt,
(self.function)(handle_args.context, handle_args.params),
)
} else {
tokio::runtime::Handle::current().block_on(local.run_until((self.function)(handle_args.context, handle_args.params)))
tokio::runtime::Handle::current()
.block_on(local.run_until((self.function)(handle_args.context, handle_args.params)))
}
}
async fn handle_async(
@@ -928,6 +1006,7 @@ where
impl<Context, F, Fut, T, E, Params, InheritedParams> HandlerFor<Context>
for FromFnAsyncLocal<F, Fut, T, E, (Context, Params, InheritedParams)>
where
Self: crate::handler::HandlerRequires<Params = Params, InheritedParams = InheritedParams, Ok = T, Err = E>,
Context: crate::Context,
F: Fn(Context, Params, InheritedParams) -> Fut + Send + Sync + Clone + 'static,
Fut: Future<Output = Result<T, E>> + 'static,
@@ -942,9 +1021,20 @@ where
) -> Result<Self::Ok, Self::Err> {
let local = tokio::task::LocalSet::new();
if let Some(rt) = handle_args.context.runtime() {
local.block_on(&*rt, (self.function)(handle_args.context, handle_args.params, handle_args.inherited_params))
local.block_on(
&*rt,
(self.function)(
handle_args.context,
handle_args.params,
handle_args.inherited_params,
),
)
} else {
tokio::runtime::Handle::current().block_on(local.run_until((self.function)(handle_args.context, handle_args.params, handle_args.inherited_params)))
tokio::runtime::Handle::current().block_on(local.run_until((self.function)(
handle_args.context,
handle_args.params,
handle_args.inherited_params,
)))
}
}
async fn handle_async(

View File

@@ -55,8 +55,34 @@ impl<Context: crate::Context, Inherited: Send + Sync> HandleAnyArgs<Context, Inh
}
}
#[cfg(feature = "ts-rs")]
pub(crate) trait HandleAnyTS {
fn params_ty(&self) -> Option<String>;
fn return_ty(&self) -> Option<String>;
}
#[cfg(feature = "ts-rs")]
impl<T: HandleAnyTS> HandleAnyTS for Arc<T> {
fn params_ty(&self) -> Option<String> {
self.deref().params_ty()
}
fn return_ty(&self) -> Option<String> {
self.deref().return_ty()
}
}
#[cfg(feature = "ts-rs")]
pub(crate) trait HandleAnyRequires: HandleAnyTS + Send + Sync {}
#[cfg(feature = "ts-rs")]
impl<T: HandleAnyTS + Send + Sync> HandleAnyRequires for T {}
#[cfg(not(feature = "ts-rs"))]
pub(crate) trait HandleAnyRequires: Send + Sync {}
#[cfg(not(feature = "ts-rs"))]
impl<T: Send + Sync> HandleAnyRequires for T {}
#[async_trait::async_trait]
pub(crate) trait HandleAny<Context>: Send + Sync {
pub(crate) trait HandleAny<Context>: HandleAnyRequires {
type Inherited: Send;
fn handle_sync(
&self,
@@ -153,6 +179,15 @@ impl<Context, Inherited> Debug for DynHandler<Context, Inherited> {
f.debug_struct("DynHandler").finish()
}
}
#[cfg(feature = "ts-rs")]
impl<Context, Inherited> HandleAnyTS for DynHandler<Context, Inherited> {
fn params_ty(&self) -> Option<String> {
self.0.params_ty()
}
fn return_ty(&self) -> Option<String> {
self.0.return_ty()
}
}
#[async_trait::async_trait]
impl<Context: crate::Context, Inherited: Send> HandleAny<Context>
for DynHandler<Context, Inherited>
@@ -206,8 +241,24 @@ pub trait HandlerTypes {
type Err: Send + Sync;
}
#[cfg(feature = "ts-rs")]
pub trait HandlerTS {
fn params_ty(&self) -> Option<String>;
fn return_ty(&self) -> Option<String>;
}
#[cfg(feature = "ts-rs")]
pub trait HandlerRequires: HandlerTS + HandlerTypes + Clone + Send + Sync + 'static {}
#[cfg(feature = "ts-rs")]
impl<T: HandlerTS + HandlerTypes + Clone + Send + Sync + 'static> HandlerRequires for T {}
#[cfg(not(feature = "ts-rs"))]
pub trait HandlerRequires: HandlerTypes + Clone + Send + Sync + 'static {}
#[cfg(not(feature = "ts-rs"))]
impl<T: HandlerTypes + Clone + Send + Sync + 'static> HandlerRequires for T {}
pub trait HandlerFor<Context: crate::Context>:
HandlerTypes + Clone + Send + Sync + 'static
HandlerRequires
{
fn handle_sync(
&self,
@@ -321,6 +372,19 @@ impl<Context, Inherited, H: std::fmt::Debug> std::fmt::Debug for AnyHandler<Cont
}
}
#[cfg(feature = "ts-rs")]
impl<Context, Inherited, H> HandleAnyTS for AnyHandler<Context, Inherited, H>
where
H: crate::handler::HandlerTS,
{
fn params_ty(&self) -> Option<String> {
self.handler.params_ty()
}
fn return_ty(&self) -> Option<String> {
self.handler.return_ty()
}
}
#[async_trait::async_trait]
impl<Context, Inherited, H> HandleAny<Context> for AnyHandler<Context, Inherited, H>
where
@@ -406,6 +470,7 @@ where
}
#[derive(Debug, Clone, Copy, Deserialize, Serialize, Parser)]
#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
pub struct Empty {}
pub trait OrEmpty<T> {

View File

@@ -12,6 +12,8 @@ use crate::{
CliBindings, DynHandler, Empty, HandleAny, HandleAnyArgs, Handler, HandlerArgs, HandlerArgsFor,
HandlerFor, HandlerTypes, WithContext,
};
#[cfg(feature = "ts-rs")]
use crate::handler::HandleAnyTS;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub(crate) struct Name(pub(crate) &'static str);
@@ -132,7 +134,7 @@ impl<Context, Params, InheritedParams> HandlerTypes
for ParentHandler<Context, Params, InheritedParams>
where
Params: Send + Sync,
InheritedParams: Send + Sync,
InheritedParams: Send + Sync,
{
type Params = Params;
type InheritedParams = InheritedParams;
@@ -140,6 +142,51 @@ where
type Err = RpcError;
}
#[cfg(feature = "ts-rs")]
impl<Context, Params, InheritedParams> crate::handler::HandlerTS for ParentHandler<Context, Params, InheritedParams>
where
Params: Send + Sync + 'static,
InheritedParams: Send + Sync + 'static,
{
fn params_ty(&self) -> Option<String> {
use std::fmt::Write;
let mut res = "{".to_owned();
for (name, handler) in &self.subcommands.1 {
let Some(ty) = handler.params_ty() else {
continue;
};
write!(
&mut res,
"{}:{};",
serde_json::to_string(&name.0).unwrap(),
ty
)
.ok();
}
res.push('}');
Some(res)
}
fn return_ty(&self) -> Option<String> {
use std::fmt::Write;
let mut res = "{".to_owned();
for (name, handler) in &self.subcommands.1 {
let Some(ty) = handler.return_ty() else {
continue;
};
write!(
&mut res,
"{}:{};",
serde_json::to_string(&name.0).unwrap(),
ty
)
.ok();
}
res.push('}');
Some(res)
}
}
impl<Context, Params, InheritedParams> HandlerFor<Context>
for ParentHandler<Context, Params, InheritedParams>
where