mirror of
https://github.com/Start9Labs/rpc-toolkit.git
synced 2026-03-26 02:11:56 +00:00
ts-rs complete
This commit is contained in:
@@ -216,11 +216,8 @@ where
|
|||||||
RemoteHandler: crate::handler::HandlerTS,
|
RemoteHandler: crate::handler::HandlerTS,
|
||||||
Extra: Send + Sync + 'static,
|
Extra: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
fn params_ty(&self) -> Option<String> {
|
fn type_info(&self) -> Option<String> {
|
||||||
self.handler.params_ty()
|
self.handler.type_info()
|
||||||
}
|
|
||||||
fn return_ty(&self) -> Option<String> {
|
|
||||||
self.handler.return_ty()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -122,11 +122,8 @@ impl<H> crate::handler::HandlerTS for NoCli<H>
|
|||||||
where
|
where
|
||||||
H: crate::handler::HandlerTS,
|
H: crate::handler::HandlerTS,
|
||||||
{
|
{
|
||||||
fn params_ty(&self) -> Option<String> {
|
fn type_info(&self) -> Option<String> {
|
||||||
self.0.params_ty()
|
self.0.type_info()
|
||||||
}
|
|
||||||
fn return_ty(&self) -> Option<String> {
|
|
||||||
self.0.return_ty()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<Context, H> HandlerFor<Context> for NoCli<H>
|
impl<Context, H> HandlerFor<Context> for NoCli<H>
|
||||||
@@ -216,11 +213,8 @@ impl<H> crate::handler::HandlerTS for NoDisplay<H>
|
|||||||
where
|
where
|
||||||
H: crate::handler::HandlerTS,
|
H: crate::handler::HandlerTS,
|
||||||
{
|
{
|
||||||
fn params_ty(&self) -> Option<String> {
|
fn type_info(&self) -> Option<String> {
|
||||||
self.0.params_ty()
|
self.0.type_info()
|
||||||
}
|
|
||||||
fn return_ty(&self) -> Option<String> {
|
|
||||||
self.0.return_ty()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,11 +333,8 @@ where
|
|||||||
H: crate::handler::HandlerTS,
|
H: crate::handler::HandlerTS,
|
||||||
P: Send + Sync + Clone + 'static,
|
P: Send + Sync + Clone + 'static,
|
||||||
{
|
{
|
||||||
fn params_ty(&self) -> Option<String> {
|
fn type_info(&self) -> Option<String> {
|
||||||
self.handler.params_ty()
|
self.handler.type_info()
|
||||||
}
|
|
||||||
fn return_ty(&self) -> Option<String> {
|
|
||||||
self.handler.return_ty()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,11 +502,8 @@ where
|
|||||||
F: Send + Sync + Clone + 'static,
|
F: Send + Sync + Clone + 'static,
|
||||||
Context: 'static,
|
Context: 'static,
|
||||||
{
|
{
|
||||||
fn params_ty(&self) -> Option<String> {
|
fn type_info(&self) -> Option<String> {
|
||||||
self.handler.params_ty()
|
self.handler.type_info()
|
||||||
}
|
|
||||||
fn return_ty(&self) -> Option<String> {
|
|
||||||
self.handler.return_ty()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -728,11 +716,8 @@ where
|
|||||||
InheritedParams: Send + Sync + 'static,
|
InheritedParams: Send + Sync + 'static,
|
||||||
H: crate::handler::HandlerTS,
|
H: crate::handler::HandlerTS,
|
||||||
{
|
{
|
||||||
fn params_ty(&self) -> Option<String> {
|
fn type_info(&self) -> Option<String> {
|
||||||
self.handler.params_ty()
|
self.handler.type_info()
|
||||||
}
|
|
||||||
fn return_ty(&self) -> Option<String> {
|
|
||||||
self.handler.return_ty()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -859,11 +844,8 @@ where
|
|||||||
H: crate::handler::HandlerTS,
|
H: crate::handler::HandlerTS,
|
||||||
M: Clone + Send + Sync + 'static,
|
M: Clone + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
fn params_ty(&self) -> Option<String> {
|
fn type_info(&self) -> Option<String> {
|
||||||
self.handler.params_ty()
|
self.handler.type_info()
|
||||||
}
|
|
||||||
fn return_ty(&self) -> Option<String> {
|
|
||||||
self.handler.return_ty()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<Context, M, H> HandlerFor<Context> for WithAbout<M, H>
|
impl<Context, M, H> HandlerFor<Context> for WithAbout<M, H>
|
||||||
|
|||||||
@@ -52,11 +52,12 @@ where
|
|||||||
<Self as HandlerTypes>::Params: ts_rs::TS,
|
<Self as HandlerTypes>::Params: ts_rs::TS,
|
||||||
<Self as HandlerTypes>::Ok: ts_rs::TS,
|
<Self as HandlerTypes>::Ok: ts_rs::TS,
|
||||||
{
|
{
|
||||||
fn params_ty(&self) -> Option<String> {
|
fn type_info(&self) -> Option<String> {
|
||||||
Some(<Self as HandlerTypes>::Params::inline())
|
Some(format!(
|
||||||
}
|
"{{_PARAMS:{},_RETURN:{}}}",
|
||||||
fn return_ty(&self) -> Option<String> {
|
<Self as HandlerTypes>::Params::inline(),
|
||||||
Some(<Self as HandlerTypes>::Ok::inline())
|
<Self as HandlerTypes>::Ok::inline(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<Context, F, T, E, Args> PrintCliResult<Context> for FromFn<F, T, E, Args>
|
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>::Params: ts_rs::TS,
|
||||||
<Self as HandlerTypes>::Ok: ts_rs::TS,
|
<Self as HandlerTypes>::Ok: ts_rs::TS,
|
||||||
{
|
{
|
||||||
fn params_ty(&self) -> Option<String> {
|
fn type_info(&self) -> Option<String> {
|
||||||
Some(<Self as HandlerTypes>::Params::inline())
|
Some(format!(
|
||||||
}
|
"{{_PARAMS:{},_RETURN:{}}}",
|
||||||
fn return_ty(&self) -> Option<String> {
|
<Self as HandlerTypes>::Params::inline(),
|
||||||
Some(<Self as HandlerTypes>::Ok::inline())
|
<Self as HandlerTypes>::Ok::inline(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<Context, F, Fut, T, E, Args> PrintCliResult<Context> for FromFnAsync<F, Fut, T, E, Args>
|
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>::Params: ts_rs::TS,
|
||||||
<Self as HandlerTypes>::Ok: ts_rs::TS,
|
<Self as HandlerTypes>::Ok: ts_rs::TS,
|
||||||
{
|
{
|
||||||
fn params_ty(&self) -> Option<String> {
|
fn type_info(&self) -> Option<String> {
|
||||||
Some(<Self as HandlerTypes>::Params::inline())
|
Some(format!(
|
||||||
}
|
"{{_PARAMS:{},_RETURN:{}}}",
|
||||||
fn return_ty(&self) -> Option<String> {
|
<Self as HandlerTypes>::Params::inline(),
|
||||||
Some(<Self as HandlerTypes>::Ok::inline())
|
<Self as HandlerTypes>::Ok::inline(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<Context, F, Fut, T, E, Args> PrintCliResult<Context> for FromFnAsyncLocal<F, Fut, T, E, Args>
|
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>
|
impl<Context, F, T, E, Params, InheritedParams> HandlerFor<Context>
|
||||||
for FromFn<F, T, E, (Context, Params, InheritedParams)>
|
for FromFn<F, T, E, (Context, Params, InheritedParams)>
|
||||||
where
|
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,
|
Context: crate::Context,
|
||||||
F: Fn(Context, Params, InheritedParams) -> Result<T, E> + Send + Sync + Clone + 'static,
|
F: Fn(Context, Params, InheritedParams) -> Result<T, E> + Send + Sync + Clone + 'static,
|
||||||
Params: DeserializeOwned + Send + Sync + 'static,
|
Params: DeserializeOwned + Send + Sync + 'static,
|
||||||
@@ -765,7 +773,12 @@ where
|
|||||||
impl<Context, F, Fut, T, E, Params, InheritedParams> HandlerFor<Context>
|
impl<Context, F, Fut, T, E, Params, InheritedParams> HandlerFor<Context>
|
||||||
for FromFnAsync<F, Fut, T, E, (Context, Params, InheritedParams)>
|
for FromFnAsync<F, Fut, T, E, (Context, Params, InheritedParams)>
|
||||||
where
|
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,
|
Context: crate::Context,
|
||||||
F: Fn(Context, Params, InheritedParams) -> Fut + Send + Sync + Clone + 'static,
|
F: Fn(Context, Params, InheritedParams) -> Fut + Send + Sync + Clone + 'static,
|
||||||
Fut: Future<Output = Result<T, E>> + Send + 'static,
|
Fut: Future<Output = Result<T, E>> + Send + 'static,
|
||||||
@@ -811,7 +824,12 @@ where
|
|||||||
impl<F, Fut, T, E, Context, Params, InheritedParams> HandlerFor<Context>
|
impl<F, Fut, T, E, Context, Params, InheritedParams> HandlerFor<Context>
|
||||||
for FromFnAsyncLocal<F, Fut, T, E, HandlerArgs<Context, Params, InheritedParams>>
|
for FromFnAsyncLocal<F, Fut, T, E, HandlerArgs<Context, Params, InheritedParams>>
|
||||||
where
|
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,
|
F: Fn(HandlerArgs<Context, Params, InheritedParams>) -> Fut + Send + Sync + Clone + 'static,
|
||||||
Fut: Future<Output = Result<T, E>> + 'static,
|
Fut: Future<Output = Result<T, E>> + 'static,
|
||||||
T: Send + Sync + 'static,
|
T: Send + Sync + 'static,
|
||||||
@@ -1006,7 +1024,12 @@ where
|
|||||||
impl<Context, F, Fut, T, E, Params, InheritedParams> HandlerFor<Context>
|
impl<Context, F, Fut, T, E, Params, InheritedParams> HandlerFor<Context>
|
||||||
for FromFnAsyncLocal<F, Fut, T, E, (Context, Params, InheritedParams)>
|
for FromFnAsyncLocal<F, Fut, T, E, (Context, Params, InheritedParams)>
|
||||||
where
|
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,
|
Context: crate::Context,
|
||||||
F: Fn(Context, Params, InheritedParams) -> Fut + Send + Sync + Clone + 'static,
|
F: Fn(Context, Params, InheritedParams) -> Fut + Send + Sync + Clone + 'static,
|
||||||
Fut: Future<Output = Result<T, E>> + 'static,
|
Fut: Future<Output = Result<T, E>> + 'static,
|
||||||
|
|||||||
@@ -57,17 +57,13 @@ impl<Context: crate::Context, Inherited: Send + Sync> HandleAnyArgs<Context, Inh
|
|||||||
|
|
||||||
#[cfg(feature = "ts-rs")]
|
#[cfg(feature = "ts-rs")]
|
||||||
pub(crate) trait HandleAnyTS {
|
pub(crate) trait HandleAnyTS {
|
||||||
fn params_ty(&self) -> Option<String>;
|
fn type_info(&self) -> Option<String>;
|
||||||
fn return_ty(&self) -> Option<String>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ts-rs")]
|
#[cfg(feature = "ts-rs")]
|
||||||
impl<T: HandleAnyTS> HandleAnyTS for Arc<T> {
|
impl<T: HandleAnyTS> HandleAnyTS for Arc<T> {
|
||||||
fn params_ty(&self) -> Option<String> {
|
fn type_info(&self) -> Option<String> {
|
||||||
self.deref().params_ty()
|
self.deref().type_info()
|
||||||
}
|
|
||||||
fn return_ty(&self) -> Option<String> {
|
|
||||||
self.deref().return_ty()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,11 +177,8 @@ impl<Context, Inherited> Debug for DynHandler<Context, Inherited> {
|
|||||||
}
|
}
|
||||||
#[cfg(feature = "ts-rs")]
|
#[cfg(feature = "ts-rs")]
|
||||||
impl<Context, Inherited> HandleAnyTS for DynHandler<Context, Inherited> {
|
impl<Context, Inherited> HandleAnyTS for DynHandler<Context, Inherited> {
|
||||||
fn params_ty(&self) -> Option<String> {
|
fn type_info(&self) -> Option<String> {
|
||||||
self.0.params_ty()
|
self.0.type_info()
|
||||||
}
|
|
||||||
fn return_ty(&self) -> Option<String> {
|
|
||||||
self.0.return_ty()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
@@ -243,8 +236,7 @@ pub trait HandlerTypes {
|
|||||||
|
|
||||||
#[cfg(feature = "ts-rs")]
|
#[cfg(feature = "ts-rs")]
|
||||||
pub trait HandlerTS {
|
pub trait HandlerTS {
|
||||||
fn params_ty(&self) -> Option<String>;
|
fn type_info(&self) -> Option<String>;
|
||||||
fn return_ty(&self) -> Option<String>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ts-rs")]
|
#[cfg(feature = "ts-rs")]
|
||||||
@@ -257,9 +249,7 @@ pub trait HandlerRequires: HandlerTypes + Clone + Send + Sync + 'static {}
|
|||||||
#[cfg(not(feature = "ts-rs"))]
|
#[cfg(not(feature = "ts-rs"))]
|
||||||
impl<T: HandlerTypes + Clone + Send + Sync + 'static> HandlerRequires for T {}
|
impl<T: HandlerTypes + Clone + Send + Sync + 'static> HandlerRequires for T {}
|
||||||
|
|
||||||
pub trait HandlerFor<Context: crate::Context>:
|
pub trait HandlerFor<Context: crate::Context>: HandlerRequires {
|
||||||
HandlerRequires
|
|
||||||
{
|
|
||||||
fn handle_sync(
|
fn handle_sync(
|
||||||
&self,
|
&self,
|
||||||
handle_args: HandlerArgsFor<Context, Self>,
|
handle_args: HandlerArgsFor<Context, Self>,
|
||||||
@@ -377,11 +367,8 @@ impl<Context, Inherited, H> HandleAnyTS for AnyHandler<Context, Inherited, H>
|
|||||||
where
|
where
|
||||||
H: crate::handler::HandlerTS,
|
H: crate::handler::HandlerTS,
|
||||||
{
|
{
|
||||||
fn params_ty(&self) -> Option<String> {
|
fn type_info(&self) -> Option<String> {
|
||||||
self.handler.params_ty()
|
self.handler.type_info()
|
||||||
}
|
|
||||||
fn return_ty(&self) -> Option<String> {
|
|
||||||
self.handler.return_ty()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,6 +458,7 @@ where
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Deserialize, Serialize, Parser)]
|
#[derive(Debug, Clone, Copy, Deserialize, Serialize, Parser)]
|
||||||
#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
|
#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
|
||||||
|
#[cfg_attr(feature = "ts-rs", ts(type = "{}"))]
|
||||||
pub struct Empty {}
|
pub struct Empty {}
|
||||||
|
|
||||||
pub trait OrEmpty<T> {
|
pub trait OrEmpty<T> {
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ use imbl_value::Value;
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use yajrc::RpcError;
|
use yajrc::RpcError;
|
||||||
|
|
||||||
|
#[cfg(feature = "ts-rs")]
|
||||||
|
use crate::handler::HandleAnyTS;
|
||||||
use crate::util::{combine, Flat, PhantomData};
|
use crate::util::{combine, Flat, PhantomData};
|
||||||
use crate::{
|
use crate::{
|
||||||
CliBindings, DynHandler, Empty, HandleAny, HandleAnyArgs, Handler, HandlerArgs, HandlerArgsFor,
|
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)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub(crate) struct Name(pub(crate) &'static str);
|
pub(crate) struct Name(pub(crate) &'static str);
|
||||||
@@ -143,46 +143,34 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ts-rs")]
|
#[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
|
where
|
||||||
Params: Send + Sync + 'static,
|
Params: ts_rs::TS + Send + Sync + 'static,
|
||||||
InheritedParams: Send + Sync + 'static,
|
InheritedParams: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
fn params_ty(&self) -> Option<String> {
|
fn type_info(&self) -> Option<String> {
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
let mut res = "{".to_owned();
|
let mut res = "{".to_owned();
|
||||||
|
res.push_str("_CHILDREN:{");
|
||||||
for (name, handler) in &self.subcommands.1 {
|
for (name, handler) in &self.subcommands.1 {
|
||||||
let Some(ty) = handler.params_ty() else {
|
let Some(ty) = handler.type_info() else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
write!(
|
write!(
|
||||||
&mut res,
|
&mut res,
|
||||||
"{}:{};",
|
"{}:{};",
|
||||||
serde_json::to_string(&name.0).unwrap(),
|
serde_json::to_string(&name.0).unwrap(),
|
||||||
ty
|
ty,
|
||||||
)
|
)
|
||||||
.ok();
|
.ok()?;
|
||||||
}
|
}
|
||||||
res.push('}');
|
res.push_str("};}");
|
||||||
Some(res)
|
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()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
Some(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,6 +178,12 @@ where
|
|||||||
impl<Context, Params, InheritedParams> HandlerFor<Context>
|
impl<Context, Params, InheritedParams> HandlerFor<Context>
|
||||||
for ParentHandler<Context, Params, InheritedParams>
|
for ParentHandler<Context, Params, InheritedParams>
|
||||||
where
|
where
|
||||||
|
Self: HandlerRequires<
|
||||||
|
Params = Params,
|
||||||
|
InheritedParams = InheritedParams,
|
||||||
|
Ok = Value,
|
||||||
|
Err = RpcError,
|
||||||
|
>,
|
||||||
Context: crate::Context,
|
Context: crate::Context,
|
||||||
Params: Send + Sync + 'static,
|
Params: Send + Sync + 'static,
|
||||||
InheritedParams: Send + Sync + 'static,
|
InheritedParams: Send + Sync + 'static,
|
||||||
|
|||||||
@@ -13,3 +13,8 @@ mod context;
|
|||||||
mod handler;
|
mod handler;
|
||||||
mod server;
|
mod server;
|
||||||
pub mod util;
|
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
41
src/type-helpers.ts
Normal 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;
|
||||||
251
tests/handler.rs
251
tests/handler.rs
@@ -1,251 +0,0 @@
|
|||||||
use std::ffi::OsString;
|
|
||||||
use std::fmt::Display;
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use clap::Parser;
|
|
||||||
use futures::future::ready;
|
|
||||||
use imbl_value::Value;
|
|
||||||
use rpc_toolkit::{
|
|
||||||
call_remote_socket, from_fn, from_fn_async, CallRemote, CliApp, Context, Empty, HandlerExt,
|
|
||||||
ParentHandler, Server,
|
|
||||||
};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use tokio::runtime::Runtime;
|
|
||||||
use tokio::sync::{Mutex, OnceCell};
|
|
||||||
use yajrc::RpcError;
|
|
||||||
|
|
||||||
#[derive(Parser, Deserialize)]
|
|
||||||
#[command(
|
|
||||||
name = "test-cli",
|
|
||||||
version,
|
|
||||||
author,
|
|
||||||
about = "This is a test cli application."
|
|
||||||
)]
|
|
||||||
struct CliConfig {
|
|
||||||
#[arg(long = "host")]
|
|
||||||
host: Option<PathBuf>,
|
|
||||||
#[arg(short = 'c', long = "config")]
|
|
||||||
config: Option<PathBuf>,
|
|
||||||
}
|
|
||||||
impl CliConfig {
|
|
||||||
fn load_rec(&mut self) -> Result<(), RpcError> {
|
|
||||||
if let Some(path) = self.config.as_ref() {
|
|
||||||
let mut extra_cfg: Self =
|
|
||||||
serde_json::from_str(&std::fs::read_to_string(path).map_err(internal_error)?)
|
|
||||||
.map_err(internal_error)?;
|
|
||||||
extra_cfg.load_rec()?;
|
|
||||||
self.merge_with(extra_cfg);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn merge_with(&mut self, extra: Self) {
|
|
||||||
if self.host.is_none() {
|
|
||||||
self.host = extra.host;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CliContextSeed {
|
|
||||||
host: PathBuf,
|
|
||||||
rt: OnceCell<Arc<Runtime>>,
|
|
||||||
}
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct CliContext(Arc<CliContextSeed>);
|
|
||||||
impl Context for CliContext {
|
|
||||||
fn runtime(&self) -> Option<Arc<Runtime>> {
|
|
||||||
if self.0.rt.get().is_none() {
|
|
||||||
let rt = Arc::new(Runtime::new().unwrap());
|
|
||||||
self.0.rt.set(rt.clone()).unwrap_or_default();
|
|
||||||
Some(rt)
|
|
||||||
} else {
|
|
||||||
self.0.rt.get().cloned()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CallRemote<ServerContext> for CliContext {
|
|
||||||
async fn call_remote(&self, method: &str, params: Value, _: Empty) -> Result<Value, RpcError> {
|
|
||||||
call_remote_socket(
|
|
||||||
tokio::net::UnixStream::connect(&self.0.host).await.unwrap(),
|
|
||||||
method,
|
|
||||||
params,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_cli() -> CliApp<CliContext, CliConfig> {
|
|
||||||
CliApp::new(
|
|
||||||
|mut config: CliConfig| {
|
|
||||||
config.load_rec()?;
|
|
||||||
Ok(CliContext(Arc::new(CliContextSeed {
|
|
||||||
host: config
|
|
||||||
.host
|
|
||||||
.unwrap_or_else(|| Path::new("./rpc.sock").to_owned()),
|
|
||||||
rt: OnceCell::new(),
|
|
||||||
})))
|
|
||||||
},
|
|
||||||
make_api(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ServerContextSeed {
|
|
||||||
state: Mutex<Value>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct ServerContext(Arc<ServerContextSeed>);
|
|
||||||
impl Context for ServerContext {}
|
|
||||||
|
|
||||||
fn make_server() -> Server<ServerContext> {
|
|
||||||
let ctx = ServerContext(Arc::new(ServerContextSeed {
|
|
||||||
state: Mutex::new(Value::Null),
|
|
||||||
}));
|
|
||||||
Server::new(move || ready(Ok(ctx.clone())), make_api())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_api<C: Context>() -> ParentHandler<C> {
|
|
||||||
async fn a_hello(_: CliContext) -> Result<String, RpcError> {
|
|
||||||
Ok::<_, RpcError>("Async Subcommand".to_string())
|
|
||||||
}
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, Parser)]
|
|
||||||
struct EchoParams {
|
|
||||||
next: String,
|
|
||||||
}
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, Parser)]
|
|
||||||
struct HelloParams {
|
|
||||||
whom: String,
|
|
||||||
}
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, Parser)]
|
|
||||||
struct InheritParams {
|
|
||||||
donde: String,
|
|
||||||
}
|
|
||||||
ParentHandler::<C>::new()
|
|
||||||
.subcommand(
|
|
||||||
"echo",
|
|
||||||
from_fn_async(
|
|
||||||
|c: ServerContext, EchoParams { next }: EchoParams| async move {
|
|
||||||
Ok::<_, RpcError>(std::mem::replace(
|
|
||||||
&mut *c.0.state.lock().await,
|
|
||||||
Value::String(Arc::new(next)),
|
|
||||||
))
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.with_custom_display_fn(|_, a| Ok(println!("{a}")))
|
|
||||||
.with_about("Testing")
|
|
||||||
.with_call_remote::<CliContext>(),
|
|
||||||
)
|
|
||||||
.subcommand(
|
|
||||||
"hello",
|
|
||||||
from_fn(|_: C, HelloParams { whom }: HelloParams| {
|
|
||||||
Ok::<_, RpcError>(format!("Hello {whom}").to_string())
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.subcommand("a_hello", from_fn_async(a_hello))
|
|
||||||
.subcommand(
|
|
||||||
"dondes",
|
|
||||||
ParentHandler::<C, InheritParams>::new().subcommand(
|
|
||||||
"donde",
|
|
||||||
from_fn(|c: CliContext, _: (), donde| {
|
|
||||||
Ok::<_, RpcError>(
|
|
||||||
format!(
|
|
||||||
"Subcommand No Cli: Host {host} Donde = {donde}",
|
|
||||||
host = c.0.host.display()
|
|
||||||
)
|
|
||||||
.to_string(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.with_inherited(|InheritParams { donde }, _| donde)
|
|
||||||
.no_cli(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.subcommand(
|
|
||||||
"fizz",
|
|
||||||
ParentHandler::<C, InheritParams>::new().root_handler(
|
|
||||||
from_fn(|c: CliContext, _: Empty, InheritParams { donde }| {
|
|
||||||
Ok::<_, RpcError>(
|
|
||||||
format!(
|
|
||||||
"Root Command: Host {host} Donde = {donde}",
|
|
||||||
host = c.0.host.display(),
|
|
||||||
)
|
|
||||||
.to_string(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.with_inherited(|a, _| a),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.subcommand(
|
|
||||||
"error",
|
|
||||||
ParentHandler::<C, InheritParams>::new().root_handler(
|
|
||||||
from_fn(|_: CliContext, _: Empty, InheritParams { .. }| {
|
|
||||||
Err::<String, _>(RpcError {
|
|
||||||
code: 1,
|
|
||||||
message: "This is an example message".into(),
|
|
||||||
data: None,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.with_inherited(|a, _| a)
|
|
||||||
.no_cli(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn internal_error(e: impl Display) -> RpcError {
|
|
||||||
RpcError {
|
|
||||||
data: Some(e.to_string().into()),
|
|
||||||
..yajrc::INTERNAL_ERROR
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_cli() {
|
|
||||||
make_cli()
|
|
||||||
.run(["test-cli", "hello", "me"].iter().map(OsString::from))
|
|
||||||
.unwrap();
|
|
||||||
make_cli()
|
|
||||||
.run(["test-cli", "fizz", "buzz"].iter().map(OsString::from))
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn test_server() {
|
|
||||||
let path = Path::new(env!("CARGO_TARGET_TMPDIR")).join("rpc.sock");
|
|
||||||
tokio::fs::remove_file(&path).await.unwrap_or_default();
|
|
||||||
let server = make_server();
|
|
||||||
let (shutdown, fut) = server
|
|
||||||
.run_unix(path.clone(), |err| eprintln!("IO Error: {err}"))
|
|
||||||
.unwrap();
|
|
||||||
tokio::join!(
|
|
||||||
tokio::task::spawn_blocking(move || {
|
|
||||||
make_cli()
|
|
||||||
.run(
|
|
||||||
[
|
|
||||||
"test-cli",
|
|
||||||
&format!("--host={}", path.display()),
|
|
||||||
"echo",
|
|
||||||
"foo",
|
|
||||||
]
|
|
||||||
.iter()
|
|
||||||
.map(OsString::from),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
make_cli()
|
|
||||||
.run(
|
|
||||||
[
|
|
||||||
"test-cli",
|
|
||||||
&format!("--host={}", path.display()),
|
|
||||||
"echo",
|
|
||||||
"bar",
|
|
||||||
]
|
|
||||||
.iter()
|
|
||||||
.map(OsString::from),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
shutdown.shutdown()
|
|
||||||
}),
|
|
||||||
fut
|
|
||||||
)
|
|
||||||
.0
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
166
tests/test.rs
166
tests/test.rs
@@ -1,109 +1,77 @@
|
|||||||
// use std::path::PathBuf;
|
use clap::Parser;
|
||||||
|
use rpc_toolkit::{from_fn_async, Context, Empty, HandlerTS, ParentHandler, Server};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use yajrc::RpcError;
|
||||||
|
|
||||||
// use clap::Parser;
|
#[derive(Clone)]
|
||||||
// use futures::Future;
|
struct TestContext;
|
||||||
// use rpc_toolkit::{
|
|
||||||
// AsyncCommand, CliContextSocket, Command, Contains, Context, DynCommand, LeafCommand, NoParent,
|
|
||||||
// ParentCommand, ParentInfo, Server, ShutdownHandle,
|
|
||||||
// };
|
|
||||||
// use serde::{Deserialize, Serialize};
|
|
||||||
// use tokio::net::UnixStream;
|
|
||||||
// use yajrc::RpcError;
|
|
||||||
|
|
||||||
// struct ServerContext;
|
impl Context for TestContext {}
|
||||||
// impl Context for ServerContext {
|
|
||||||
// type Metadata = ();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// struct CliContext(PathBuf);
|
#[derive(Debug, Deserialize, Serialize, Parser)]
|
||||||
// impl Context for CliContext {
|
#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
|
||||||
// type Metadata = ();
|
struct Thing1Params {
|
||||||
// }
|
thing: String,
|
||||||
|
}
|
||||||
|
|
||||||
// impl CliContextSocket for CliContext {
|
async fn thing1_handler(_ctx: TestContext, params: Thing1Params) -> Result<String, RpcError> {
|
||||||
// type Stream = UnixStream;
|
Ok(format!("Thing1 is {}", params.thing))
|
||||||
// async fn connect(&self) -> std::io::Result<Self::Stream> {
|
}
|
||||||
// UnixStream::connect(&self.0).await
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl rpc_toolkit::CliContext for CliContext {
|
#[derive(Debug, Deserialize, Serialize, Parser)]
|
||||||
// async fn call_remote(
|
#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
|
||||||
// &self,
|
struct GroupParams {
|
||||||
// method: &str,
|
#[arg(short, long)]
|
||||||
// params: imbl_value::Value,
|
verbose: bool,
|
||||||
// ) -> Result<imbl_value::Value, RpcError> {
|
}
|
||||||
// <Self as CliContextSocket>::call_remote(self, method, params).await
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// async fn run_server() {
|
#[tokio::test]
|
||||||
// Server::new(
|
async fn test_basic_server() {
|
||||||
// vec![
|
let root_handler = ParentHandler::new()
|
||||||
// DynCommand::from_parent::<Group>(Contains::none()),
|
.subcommand("thing1", from_fn_async(thing1_handler))
|
||||||
// DynCommand::from_async::<Thing1>(Contains::none()),
|
.subcommand(
|
||||||
// // DynCommand::from_async::<Thing2>(Contains::none()),
|
"group",
|
||||||
// // DynCommand::from_sync::<Thing3>(Contains::none()),
|
ParentHandler::<TestContext, Empty, Empty>::new()
|
||||||
// // DynCommand::from_sync::<Thing4>(Contains::none()),
|
.subcommand("thing1", from_fn_async(thing1_handler))
|
||||||
// ],
|
.subcommand(
|
||||||
// || async { Ok(ServerContext) },
|
"thing2",
|
||||||
// )
|
from_fn_async(|_ctx: TestContext, params: GroupParams| async move {
|
||||||
// .run_unix("./test.sock", |e| eprintln!("{e}"))
|
Ok::<_, RpcError>(format!("verbose: {}", params.verbose))
|
||||||
// .unwrap()
|
}),
|
||||||
// .1
|
),
|
||||||
// .await
|
);
|
||||||
// }
|
|
||||||
|
|
||||||
// #[derive(Debug, Deserialize, Serialize, Parser)]
|
println!("{}", root_handler.type_info().unwrap_or_default());
|
||||||
// struct Group {
|
|
||||||
// #[arg(short, long)]
|
|
||||||
// verbose: bool,
|
|
||||||
// }
|
|
||||||
// impl Command for Group {
|
|
||||||
// const NAME: &'static str = "group";
|
|
||||||
// type Parent = NoParent;
|
|
||||||
// }
|
|
||||||
// impl<Ctx> ParentCommand<Ctx> for Group
|
|
||||||
// where
|
|
||||||
// Ctx: Context,
|
|
||||||
// // SubThing: AsyncCommand<Ctx>,
|
|
||||||
// Thing1: AsyncCommand<Ctx>,
|
|
||||||
// {
|
|
||||||
// fn subcommands(chain: rpc_toolkit::ParentChain<Self>) -> Vec<DynCommand<Ctx>> {
|
|
||||||
// vec![
|
|
||||||
// // DynCommand::from_async::<SubThing>(chain.child()),
|
|
||||||
// DynCommand::from_async::<Thing1>(Contains::none()),
|
|
||||||
// ]
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[derive(Debug, Deserialize, Serialize, Parser)]
|
let server = Server::new(|| async { Ok(TestContext) }, root_handler);
|
||||||
// struct Thing1 {
|
|
||||||
// thing: String,
|
|
||||||
// }
|
|
||||||
// impl Command for Thing1 {
|
|
||||||
// const NAME: &'static str = "thing1";
|
|
||||||
// type Parent = NoParent;
|
|
||||||
// }
|
|
||||||
// impl LeafCommand<ServerContext> for Thing1 {
|
|
||||||
// type Ok = String;
|
|
||||||
// type Err = RpcError;
|
|
||||||
// fn display(self, _: ServerContext, _: rpc_toolkit::ParentInfo<Self::Parent>, res: Self::Ok) {
|
|
||||||
// println!("{}", res);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl AsyncCommand<ServerContext> for Thing1 {
|
// Test calling thing1 directly
|
||||||
// async fn implementation(
|
let result = server
|
||||||
// self,
|
.handle_command(
|
||||||
// _: ServerContext,
|
"thing1",
|
||||||
// _: ParentInfo<Self::Parent>,
|
imbl_value::to_value(&Thing1Params {
|
||||||
// ) -> Result<Self::Ok, Self::Err> {
|
thing: "test".to_string(),
|
||||||
// Ok(format!("Thing1 is {}", self.thing))
|
})
|
||||||
// }
|
.unwrap(),
|
||||||
// }
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// #[tokio::test]
|
let response: String = imbl_value::from_value(result).unwrap();
|
||||||
// async fn test() {
|
assert_eq!(response, "Thing1 is test");
|
||||||
// let server = tokio::spawn(run_server());
|
|
||||||
// }
|
// Test calling group.thing1
|
||||||
|
let result = server
|
||||||
|
.handle_command(
|
||||||
|
"group.thing1",
|
||||||
|
imbl_value::to_value(&Thing1Params {
|
||||||
|
thing: "nested".to_string(),
|
||||||
|
})
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let response: String = imbl_value::from_value(result).unwrap();
|
||||||
|
assert_eq!(response, "Thing1 is nested");
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user