ts-rs complete

This commit is contained in:
Aiden McClelland
2025-11-07 01:47:11 -07:00
parent 9d75ab4610
commit 7667b1adaf
9 changed files with 202 additions and 455 deletions

View File

@@ -216,11 +216,8 @@ 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()
fn type_info(&self) -> Option<String> {
self.handler.type_info()
}
}

View File

@@ -122,11 +122,8 @@ 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()
fn type_info(&self) -> Option<String> {
self.0.type_info()
}
}
impl<Context, H> HandlerFor<Context> for NoCli<H>
@@ -216,11 +213,8 @@ 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()
fn type_info(&self) -> Option<String> {
self.0.type_info()
}
}
@@ -339,11 +333,8 @@ 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()
fn type_info(&self) -> Option<String> {
self.handler.type_info()
}
}
@@ -511,11 +502,8 @@ where
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()
fn type_info(&self) -> Option<String> {
self.handler.type_info()
}
}
@@ -728,11 +716,8 @@ where
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()
fn type_info(&self) -> Option<String> {
self.handler.type_info()
}
}
@@ -859,11 +844,8 @@ 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()
fn type_info(&self) -> Option<String> {
self.handler.type_info()
}
}
impl<Context, M, H> HandlerFor<Context> for WithAbout<M, H>

View File

@@ -52,11 +52,12 @@ where
<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())
fn type_info(&self) -> Option<String> {
Some(format!(
"{{_PARAMS:{},_RETURN:{}}}",
<Self as HandlerTypes>::Params::inline(),
<Self as HandlerTypes>::Ok::inline(),
))
}
}
impl<Context, F, T, E, Args> PrintCliResult<Context> for FromFn<F, T, E, Args>
@@ -174,11 +175,12 @@ where
<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())
fn type_info(&self) -> Option<String> {
Some(format!(
"{{_PARAMS:{},_RETURN:{}}}",
<Self as HandlerTypes>::Params::inline(),
<Self as HandlerTypes>::Ok::inline(),
))
}
}
impl<Context, F, Fut, T, E, Args> PrintCliResult<Context> for FromFnAsync<F, Fut, T, E, Args>
@@ -283,11 +285,12 @@ where
<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())
fn type_info(&self) -> Option<String> {
Some(format!(
"{{_PARAMS:{},_RETURN:{}}}",
<Self as HandlerTypes>::Params::inline(),
<Self as HandlerTypes>::Ok::inline(),
))
}
}
impl<Context, F, Fut, T, E, Args> PrintCliResult<Context> for FromFnAsyncLocal<F, Fut, T, E, Args>
@@ -711,7 +714,12 @@ 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>,
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,
@@ -765,7 +773,12 @@ 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>,
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,
@@ -811,7 +824,12 @@ 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>,
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,
@@ -1006,7 +1024,12 @@ 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>,
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,

View File

@@ -57,17 +57,13 @@ 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>;
fn type_info(&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()
fn type_info(&self) -> Option<String> {
self.deref().type_info()
}
}
@@ -181,11 +177,8 @@ impl<Context, Inherited> Debug for DynHandler<Context, Inherited> {
}
#[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()
fn type_info(&self) -> Option<String> {
self.0.type_info()
}
}
#[async_trait::async_trait]
@@ -243,8 +236,7 @@ pub trait HandlerTypes {
#[cfg(feature = "ts-rs")]
pub trait HandlerTS {
fn params_ty(&self) -> Option<String>;
fn return_ty(&self) -> Option<String>;
fn type_info(&self) -> Option<String>;
}
#[cfg(feature = "ts-rs")]
@@ -257,9 +249,7 @@ 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>:
HandlerRequires
{
pub trait HandlerFor<Context: crate::Context>: HandlerRequires {
fn handle_sync(
&self,
handle_args: HandlerArgsFor<Context, Self>,
@@ -377,11 +367,8 @@ 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()
fn type_info(&self) -> Option<String> {
self.handler.type_info()
}
}
@@ -471,6 +458,7 @@ where
#[derive(Debug, Clone, Copy, Deserialize, Serialize, Parser)]
#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
#[cfg_attr(feature = "ts-rs", ts(type = "{}"))]
pub struct Empty {}
pub trait OrEmpty<T> {

View File

@@ -7,13 +7,13 @@ use imbl_value::Value;
use serde::Serialize;
use yajrc::RpcError;
#[cfg(feature = "ts-rs")]
use crate::handler::HandleAnyTS;
use crate::util::{combine, Flat, PhantomData};
use crate::{
CliBindings, DynHandler, Empty, HandleAny, HandleAnyArgs, Handler, HandlerArgs, HandlerArgsFor,
HandlerFor, HandlerTypes, WithContext,
HandlerFor, HandlerRequires, 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);
@@ -134,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;
@@ -143,46 +143,34 @@ where
}
#[cfg(feature = "ts-rs")]
impl<Context, Params, InheritedParams> crate::handler::HandlerTS for ParentHandler<Context, Params, InheritedParams>
impl<Context, Params, InheritedParams> crate::handler::HandlerTS
for ParentHandler<Context, Params, InheritedParams>
where
Params: Send + Sync + 'static,
Params: ts_rs::TS + Send + Sync + 'static,
InheritedParams: Send + Sync + 'static,
{
fn params_ty(&self) -> Option<String> {
fn type_info(&self) -> Option<String> {
use std::fmt::Write;
let mut res = "{".to_owned();
res.push_str("_CHILDREN:{");
for (name, handler) in &self.subcommands.1 {
let Some(ty) = handler.params_ty() else {
let Some(ty) = handler.type_info() else {
continue;
};
write!(
&mut res,
"{}:{};",
serde_json::to_string(&name.0).unwrap(),
ty
ty,
)
.ok();
.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_str("};}");
if let Some(ty) = self.subcommands.0.as_ref().and_then(|h| h.type_info()) {
write!(&mut res, "&{}", ty).ok()?;
} else {
write!(&mut res, "&{{_PARAMS:{}}}", Params::inline()).ok()?;
}
res.push('}');
Some(res)
}
}
@@ -190,6 +178,12 @@ where
impl<Context, Params, InheritedParams> HandlerFor<Context>
for ParentHandler<Context, Params, InheritedParams>
where
Self: HandlerRequires<
Params = Params,
InheritedParams = InheritedParams,
Ok = Value,
Err = RpcError,
>,
Context: crate::Context,
Params: Send + Sync + 'static,
InheritedParams: Send + Sync + 'static,

View File

@@ -13,3 +13,8 @@ mod context;
mod handler;
mod server;
pub mod util;
#[cfg(feature = "ts-rs")]
pub fn type_helpers() -> &'static str {
include_str!("./type-helpers.ts")
}

41
src/type-helpers.ts Normal file
View File

@@ -0,0 +1,41 @@
export type RpcHandler = ParentHandler | LeafHandler;
export type ParentHandler = {
_CHILDREN: {
[name: string]: RpcHandler;
};
_PARAMS: unknown;
_RETURN?: unknown;
};
export type LeafHandler = {
_PARAMS: unknown;
_RETURN: unknown;
};
export type RpcParamType<
Root extends RpcHandler,
Method extends string
> = Root["_PARAMS"] &
(Root extends ParentHandler
? Method extends `${infer A}.${infer B}`
? RpcParamType<Root["_CHILDREN"][A], B>
: Root["_CHILDREN"] extends {
[m in Method]: LeafHandler;
}
? Root["_CHILDREN"][Method]["_PARAMS"]
: never
: never);
export type RpcReturnType<
Root extends RpcHandler,
Method extends string
> = Root extends ParentHandler
? Method extends `${infer A}.${infer B}`
? RpcReturnType<Root["_CHILDREN"][A], B>
: Root["_CHILDREN"] extends {
[m in Method]: LeafHandler;
}
? Root["_CHILDREN"][Method]["_RETURN"]
: never
: never;