wip: replace ts lib

This commit is contained in:
Aiden McClelland
2025-11-12 10:57:37 -07:00
parent 2dd2832e04
commit c2bb290618
10 changed files with 143 additions and 82 deletions

65
Cargo.lock generated
View File

@@ -1198,8 +1198,8 @@ dependencies = [
"thiserror 2.0.17",
"tokio",
"tokio-stream",
"ts-rs",
"url",
"visit-rs",
"yajrc",
]
@@ -1495,15 +1495,6 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "termcolor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
]
[[package]]
name = "thiserror"
version = "1.0.69"
@@ -1704,28 +1695,6 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "ts-rs"
version = "9.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b44017f9f875786e543595076374b9ef7d13465a518dd93d6ccdbf5b432dde8c"
dependencies = [
"thiserror 1.0.69",
"ts-rs-macros",
]
[[package]]
name = "ts-rs-macros"
version = "9.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c88cc88fd23b5a04528f3a8436024f20010a16ec18eb23c164b1242f65860130"
dependencies = [
"proc-macro2",
"quote",
"syn",
"termcolor",
]
[[package]]
name = "unicode-ident"
version = "1.0.22"
@@ -1774,6 +1743,29 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "visit-rs"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ea0fdb05dd98029f7e226ccd11bd7184ad68566365547930bdde9ae79b5ce3d"
dependencies = [
"async-stream",
"futures",
"serde",
"visit-rs-derive",
]
[[package]]
name = "visit-rs-derive"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8dde3216fefaf10421d9509f88bc5a480b5fb3fe48779ca4f148e75896d3f5ad"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "want"
version = "0.3.1"
@@ -1866,15 +1858,6 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "winapi-util"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "windows-link"
version = "0.1.3"

View File

@@ -1,31 +1,32 @@
[package]
authors = ["Aiden McClelland <me@drbonez.dev>"]
edition = "2018"
name = "rpc-toolkit"
version = "0.3.2"
description = "A toolkit for creating JSON-RPC 2.0 servers with automatic cli bindings"
license = "MIT"
documentation = "https://docs.rs/rpc-toolkit"
keywords = ["json", "rpc", "cli"]
edition = "2018"
keywords = ["cli", "json", "rpc"]
license = "MIT"
name = "rpc-toolkit"
repository = "https://github.com/Start9Labs/rpc-toolkit"
version = "0.3.2"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
cbor = ["serde_cbor"]
default = ["cbor", "ts-rs"]
default = ["cbor", "ts"]
ts = ["visit-rs"]
[dependencies]
axum = "0.8"
async-stream = "0.3"
async-trait = "0.1"
axum = "0.8"
clap = { version = "4", features = ["derive"] }
futures = "0.3"
http = "1"
http-body-util = "0.1"
# hyper = { version = "1", features = ["server", "http1", "http2", "client"] }
itertools = "0.14"
imbl-value = "0.4.3"
itertools = "0.14"
lazy_format = "2"
lazy_static = "1.4"
openssl = { version = "0.10", features = ["vendored"] }
@@ -37,6 +38,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"
visit-rs = { version = "0.1.5", optional = true }
yajrc = "0.1"

View File

@@ -209,7 +209,7 @@ where
type Err = RemoteHandler::Err;
}
#[cfg(feature = "ts-rs")]
#[cfg(feature = "ts")]
impl<Context, RemoteContext, RemoteHandler, Extra> crate::handler::HandlerTS
for CallRemoteHandler<Context, RemoteContext, RemoteHandler, Extra>
where

View File

@@ -139,7 +139,7 @@ impl<H: HandlerTypes> HandlerTypes for NoCli<H> {
type Ok = H::Ok;
type Err = H::Err;
}
#[cfg(feature = "ts-rs")]
#[cfg(feature = "ts")]
impl<H> crate::handler::HandlerTS for NoCli<H>
where
H: crate::handler::HandlerTS,
@@ -233,7 +233,7 @@ impl<H: HandlerTypes> HandlerTypes for NoDisplay<H> {
type Ok = H::Ok;
type Err = H::Err;
}
#[cfg(feature = "ts-rs")]
#[cfg(feature = "ts")]
impl<H> crate::handler::HandlerTS for NoDisplay<H>
where
H: crate::handler::HandlerTS,
@@ -355,7 +355,7 @@ where
type Ok = H::Ok;
type Err = H::Err;
}
#[cfg(feature = "ts-rs")]
#[cfg(feature = "ts")]
impl<P, H> crate::handler::HandlerTS for CustomDisplay<P, H>
where
H: crate::handler::HandlerTS,
@@ -526,7 +526,7 @@ where
type Ok = H::Ok;
type Err = H::Err;
}
#[cfg(feature = "ts-rs")]
#[cfg(feature = "ts")]
impl<F, H, Context> crate::handler::HandlerTS for CustomDisplayFn<F, H, Context>
where
H: crate::handler::HandlerTS,
@@ -751,7 +751,7 @@ where
type Err = H::Err;
}
#[cfg(feature = "ts-rs")]
#[cfg(feature = "ts")]
impl<Params, InheritedParams, H, F> crate::handler::HandlerTS
for InheritanceHandler<Params, InheritedParams, H, F>
where
@@ -884,7 +884,7 @@ where
type Ok = H::Ok;
type Err = H::Err;
}
#[cfg(feature = "ts-rs")]
#[cfg(feature = "ts")]
impl<M, H> crate::handler::HandlerTS for WithAbout<M, H>
where
H: crate::handler::HandlerTS,
@@ -988,7 +988,7 @@ where
type Err = H::Err;
}
#[cfg(feature = "ts-rs")]
#[cfg(feature = "ts")]
impl<H> crate::handler::HandlerTS for NoTS<H> {
fn type_info(&self) -> Option<String> {
None
@@ -1088,7 +1088,7 @@ where
type Err = H::Err;
}
#[cfg(feature = "ts-rs")]
#[cfg(feature = "ts")]
impl<H: LeafHandler> crate::handler::HandlerTS for UnknownTS<H> {
fn type_info(&self) -> Option<String> {
Some("{_PARAMS:unknown,_RETURN:unknown}".to_string())
@@ -1192,7 +1192,7 @@ where
type Err = H::Err;
}
#[cfg(feature = "ts-rs")]
#[cfg(feature = "ts")]
impl<H: LeafHandler> crate::handler::HandlerTS for CustomTS<H> {
fn type_info(&self) -> Option<String> {
Some(format!(

View File

@@ -7,9 +7,9 @@ use imbl_value::imbl::OrdMap;
use imbl_value::Value;
use serde::de::DeserializeOwned;
use serde::Serialize;
#[cfg(feature = "ts-rs")]
use ts_rs::TS;
#[cfg(feature = "ts")]
use crate::ts::TSVisitor;
use crate::util::PhantomData;
use crate::{
CliBindings, Empty, HandlerArgs, HandlerArgsFor, HandlerFor, HandlerTypes, LeafHandler,
@@ -48,14 +48,15 @@ impl<F, T, E, Args> std::fmt::Debug for FromFn<F, T, E, Args> {
}
}
#[cfg(feature = "ts-rs")]
#[cfg(feature = "ts")]
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,
visit_rs::Static<<Self as HandlerTypes>::Params>: visit_rs::Visit<TSVisitor>,
visit_rs::Static<<Self as HandlerTypes>::Ok>: visit_rs::Visit<TSVisitor>,
{
fn type_info(&self) -> Option<String> {
let mut visitor = TSVisitor::default();
Some(format!(
"{{_PARAMS:{},_RETURN:{}}}",
<Self as HandlerTypes>::Params::inline_flattened(),
@@ -173,7 +174,7 @@ impl<F, Fut, T, E, Args> std::fmt::Debug for FromFnAsync<F, Fut, T, E, Args> {
}
}
#[cfg(feature = "ts-rs")]
#[cfg(feature = "ts")]
impl<F, Fut, T, E, Args> crate::handler::HandlerTS for FromFnAsync<F, Fut, T, E, Args>
where
Self: HandlerTypes,
@@ -285,7 +286,7 @@ impl<F, Fut, T, E, Args> std::fmt::Debug for FromFnAsyncLocal<F, Fut, T, E, Args
}
}
#[cfg(feature = "ts-rs")]
#[cfg(feature = "ts")]
impl<F, Fut, T, E, Args> crate::handler::HandlerTS for FromFnAsyncLocal<F, Fut, T, E, Args>
where
Self: HandlerTypes,

View File

@@ -233,7 +233,7 @@ pub trait HandlerTS {
fn type_info(&self) -> Option<String>;
}
#[cfg(not(feature = "ts-rs"))]
#[cfg(not(feature = "ts"))]
impl<T: HandlerTypes> HandlerTS for T {
fn type_info(&self) -> Option<String> {
None
@@ -450,8 +450,8 @@ where
}
#[derive(Debug, Clone, Copy, Deserialize, Serialize, Parser)]
#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
#[cfg_attr(feature = "ts-rs", ts(type = "{}"))]
#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
#[cfg_attr(feature = "ts", ts(type = "{}"))]
pub struct Empty {}
pub trait OrEmpty<T> {

View File

@@ -7,14 +7,14 @@ use imbl_value::Value;
use serde::Serialize;
use yajrc::RpcError;
#[cfg(feature = "ts-rs")]
#[cfg(feature = "ts")]
use crate::handler::HandleAnyTS;
use crate::util::{combine, Flat, PhantomData};
use crate::{
CliBindings, DynHandler, Empty, HandleAny, HandleAnyArgs, Handler, HandlerArgs, HandlerArgsFor,
HandlerFor, HandlerRequires, HandlerTypes, WithContext,
};
#[cfg(feature = "ts-rs")]
#[cfg(feature = "ts")]
use crate::{CustomTS, UnknownTS};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
@@ -88,7 +88,7 @@ impl<Context, Params, InheritedParams> ParentHandler<Context, Params, InheritedP
self.metadata.insert(key, value);
self
}
#[cfg(feature = "ts-rs")]
#[cfg(feature = "ts")]
fn type_info_impl(&self, params_ty: &str) -> Option<String> {
use std::fmt::Write;
let mut res = "{".to_owned();
@@ -169,7 +169,7 @@ where
type Err = RpcError;
}
#[cfg(feature = "ts-rs")]
#[cfg(feature = "ts")]
impl<Context, Params, InheritedParams> crate::handler::HandlerTS
for ParentHandler<Context, Params, InheritedParams>
where
@@ -180,7 +180,7 @@ where
self.type_info_impl(&Params::inline_flattened())
}
}
#[cfg(feature = "ts-rs")]
#[cfg(feature = "ts")]
impl<Context, Params, InheritedParams> crate::handler::HandlerTS
for CustomTS<ParentHandler<Context, Params, InheritedParams>>
where
@@ -191,7 +191,7 @@ where
self.handler.type_info_impl(&self.params_ty)
}
}
#[cfg(feature = "ts-rs")]
#[cfg(feature = "ts")]
impl<Context, Params, InheritedParams> crate::handler::HandlerTS
for UnknownTS<ParentHandler<Context, Params, InheritedParams>>
where

View File

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

77
src/ts.rs Normal file
View File

@@ -0,0 +1,77 @@
use visit_rs::{NamedStatic, Static, Visit, VisitFieldsStaticNamed, Visitor};
pub fn type_helpers() -> &'static str {
include_str!("./type-helpers.ts")
}
#[derive(Default)]
pub struct TSVisitor {
pub ts: String,
}
impl Visitor for TSVisitor {
type Result = ();
}
impl<T> Visit<TSVisitor> for Static<T>
where
T: VisitFieldsStaticNamed<TSVisitor>,
{
fn visit(&self, visitor: &mut TSVisitor) -> <TSVisitor as Visitor>::Result {
if Self::IS_NAMED {
visitor.ts.push_str("{");
} else {
visitor.ts.push_str("[");
}
self.visit_fields_static_named(visitor).collect::<()>();
if Self::IS_NAMED {
visitor.ts.push_str("}");
} else {
visitor.ts.push_str("]");
}
}
}
impl<T> Visit<TSVisitor> for NamedStatic<T>
where
Static<T>: Visit<TSVisitor>,
{
fn visit(&self, visitor: &mut TSVisitor) -> <TSVisitor as Visitor>::Result {
if let Some(name) = self.name {
if name.chars().all(|c| c.is_alphanumeric() || c == '_')
&& name.chars().next().map_or(false, |c| c.is_alphabetic())
{
visitor.ts.push_str(name);
} else {
write!(
&mut visitor.ts,
"[{}]",
serde_json::to_string(&name).unwrap()
)
.unwrap();
}
visitor.ts.push_str(":");
}
Static::<T>::new().visit(visitor);
if self.name.is_some() {
visitor.ts.push(";");
} else {
visitor.ts.push(",");
}
}
}
macro_rules! impl_ts {
($($ty:ty),+ => $ts:expr) => {
$(
impl Visit<TSVisitor> for Static<$ty> {
fn visit(&self, visitor: &mut TSVisitor) -> <TSVisitor as Visitor>::Result {
visitor.ts.push_str($ts);
}
}
)+
};
}
impl_ts!(String => "string");
impl_ts!(usize,u8,u16,u32,isize,i8,i16,i32,f32,f64 => "number");
impl_ts!(u64,u128,i64,i128 => "bigint");

View File

@@ -11,7 +11,7 @@ struct TestContext;
impl Context for TestContext {}
#[derive(Debug, Deserialize, Serialize, Parser)]
#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
struct Thing1Params {
thing: String,
}
@@ -30,7 +30,7 @@ fn no_ts_handler(_ctx: TestContext, params: NoTSParams) -> Result<String, RpcErr
}
#[derive(Debug, Deserialize, Serialize, Parser)]
#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
struct GroupParams {
#[arg(short, long)]
verbose: bool,