Skip to content

Commit 7e21793

Browse files
committed
generate correct TS type, and port tests
1 parent 12af0c3 commit 7e21793

File tree

5 files changed

+89
-67
lines changed

5 files changed

+89
-67
lines changed

src/ts/handler/reflection.rs

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,3 @@ pub struct HandlerMeta {
2121
/// Name of the parameters for this handler.
2222
pub param_names: &'static [&'static str],
2323
}
24-
25-
/// All components of a handler required to initialise the
26-
/// [`RpcModule`](jsonrpsee::RpcModule), and generate TypeScript bindings for this handler.
27-
/// Instances of this struct can be called directly in order to invoke the underlying
28-
/// handler.
29-
///
30-
/// This should be generated with the [`handler`](crate::handler) macro.
31-
#[derive(Clone)]
32-
pub struct HandlerDef<F> {
33-
/// Handler implementation.
34-
pub handler: F,
35-
/// Metadata for the handler.
36-
pub meta: HandlerMeta,
37-
}
38-
39-
impl<F> std::ops::Deref for HandlerDef<F> {
40-
type Target = F;
41-
42-
fn deref(&self) -> &Self::Target {
43-
&self.handler
44-
}
45-
}

src/ts/router.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,7 @@ where
6060
F: RegisterableHandler<MSig, MValue, MReturn, Ctx = Ctx>,
6161
{
6262
let handler_meta = HANDLER_DEFINITIONS_MAP.get(&handler.type_id()).unwrap();
63-
self.ts_router
64-
.add_handler(handler_meta.name, handler_meta.param_names, &handler);
63+
self.ts_router.add_handler(handler_meta, &handler);
6564

6665
// Create the registration function for this handler.
6766
self.handler_registrations.push((

src/ts/ts.rs

Lines changed: 76 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use crate::ts::handler::ts::TsTypeTuple;
1+
use crate::ts::handler::{
2+
reflection::{HandlerKind, HandlerMeta},
3+
ts::TsTypeTuple,
4+
};
25
use std::{any::TypeId, collections::BTreeMap, fmt::Write};
36

47
use super::handler::{RegisterableHandler, marker, response::ResponseValue, ts::TsType};
@@ -31,8 +34,7 @@ impl TsRouter {
3134
MReturn: marker::HandlerReturnMarker,
3235
>(
3336
&mut self,
34-
name: impl ToString,
35-
param_names: &[impl AsRef<str>],
37+
meta: &HandlerMeta,
3638
_handler: &F,
3739
) where
3840
F: RegisterableHandler<MSig, MValue, MReturn>,
@@ -42,7 +44,7 @@ impl TsRouter {
4244

4345
assert_eq!(
4446
param_tys.len(),
45-
param_names.len(),
47+
meta.param_names.len(),
4648
"param types and provided names must be equal length"
4749
);
4850

@@ -55,18 +57,26 @@ impl TsRouter {
5557
});
5658

5759
// Generate the signature of this handler.
58-
let params = param_names
60+
let kind = match meta.kind {
61+
HandlerKind::Query => "Query",
62+
HandlerKind::Mutation => "Mutation",
63+
HandlerKind::Subscription => "Subscription",
64+
};
65+
let params = meta
66+
.param_names
5967
.iter()
6068
.zip(&param_tys)
61-
.flat_map(|(name, ty)| [format!("{}: {}", name.as_ref(), ty.name), ", ".to_string()])
62-
.take(if param_names.is_empty() {
69+
.flat_map(|(name, ty)| [format!("{}: {}", name, ty.name), ", ".to_string()])
70+
.take(if meta.param_names.is_empty() {
6371
0
6472
} else {
65-
param_names.len() * 2 - 1
73+
meta.param_names.len() * 2 - 1
6674
})
6775
.collect::<String>();
68-
self.handlers
69-
.insert(name.to_string(), format!("({params}) => {}", ret_ty.name));
76+
self.handlers.insert(
77+
meta.name.to_string(),
78+
format!("{kind}<[{params}], {}>", ret_ty.name),
79+
);
7080
}
7181

7282
/// Nest another router at a prefix.
@@ -148,25 +158,32 @@ mod test {
148158
struct CustomStruct;
149159

150160
#[rstest]
151-
#[case::empty(&[], || {}, "() => null")]
152-
#[case::ctx(&[], |ctx: ()| {}, "() => null")]
153-
#[case::param(&["a"], |ctx: (), a: usize| {}, "(a: number) => null")]
154-
#[case::multi_param(&["a", "b"], |ctx: (), a: usize, b: bool| {}, "(a: number, b: boolean) => null")]
155-
#[case::ret(&[], || -> usize { todo!() }, "() => number")]
156-
#[case::ret_ctx(&[], |ctx: ()| -> usize { todo!() }, "() => number")]
157-
#[case::custom_param(&["custom"], |ctx: (), custom: CustomStruct| {}, "(custom: CustomStruct) => null")]
158-
#[case::custom_ret(&[], |ctx: ()| -> CustomStruct { todo!() }, "() => CustomStruct")]
159-
#[case::complex_response(&[], |ctx: ()| async { CustomStruct }, "() => CustomStruct")]
160-
#[case::everything(&["a", "b", "custom"], |ctx: (), a: usize, b: String, custom: CustomStruct| async { CustomStruct }, "(a: number, b: string, custom: CustomStruct) => CustomStruct")]
161+
#[case::empty(&[], || {}, "Query<[], null>")]
162+
#[case::ctx(&[], |ctx: ()| {}, "Query<[], null>")]
163+
#[case::param(&["a"], |ctx: (), a: usize| {}, "Query<[a: number], null>")]
164+
#[case::multi_param(&["a", "b"], |ctx: (), a: usize, b: bool| {}, "Query<[a: number, b: boolean], null>")]
165+
#[case::ret(&[], || -> usize { todo!() }, "Query<[], number>")]
166+
#[case::ret_ctx(&[], |ctx: ()| -> usize { todo!() }, "Query<[], number>")]
167+
#[case::custom_param(&["custom"], |ctx: (), custom: CustomStruct| {}, "Query<[custom: CustomStruct], null>")]
168+
#[case::custom_ret(&[], |ctx: ()| -> CustomStruct { todo!() }, "Query<[], CustomStruct>")]
169+
#[case::complex_response(&[], |ctx: ()| async { CustomStruct }, "Query<[], CustomStruct>")]
170+
#[case::everything(&["a", "b", "custom"], |ctx: (), a: usize, b: String, custom: CustomStruct| async { CustomStruct }, "Query<[a: number, b: string, custom: CustomStruct], CustomStruct>")]
161171
fn test<F, MSig, MValue: marker::ResponseMarker, MReturn: marker::HandlerReturnMarker>(
162-
#[case] param_names: &[&str],
172+
#[case] param_names: &'static [&'static str],
163173
#[case] handler: F,
164174
#[case] expected: String,
165175
) where
166176
F: RegisterableHandler<MSig, MValue, MReturn>,
167177
{
168178
let mut module = TsRouter::new();
169-
module.add_handler("handler", param_names, &handler);
179+
module.add_handler(
180+
&HandlerMeta {
181+
name: "handler",
182+
param_names,
183+
kind: HandlerKind::Query,
184+
},
185+
&handler,
186+
);
170187

171188
let signature = module.handlers.get("handler").unwrap();
172189
assert_eq!(signature, &expected);
@@ -186,12 +203,17 @@ mod test {
186203
#[allow(unused)]
187204
fn user_types() {
188205
let mut module = TsRouter::new();
189-
module.add_handler("handler", &["a"], &|ctx: (), a: UserTypeA| -> UserTypeB {
190-
todo!()
191-
});
206+
module.add_handler(
207+
&HandlerMeta {
208+
name: "handler",
209+
param_names: &["a"],
210+
kind: HandlerKind::Query,
211+
},
212+
&|ctx: (), a: UserTypeA| -> UserTypeB { todo!() },
213+
);
192214

193215
let signature = module.handlers.get("handler").unwrap();
194-
assert_eq!(signature, "(a: UserTypeA) => UserTypeB");
216+
assert_eq!(signature, "Query<[a: UserTypeA], UserTypeB>");
195217

196218
assert_eq!(module.user_types.len(), 2);
197219
assert_eq!(
@@ -208,15 +230,22 @@ mod test {
208230
fn make_router(handlers: impl IntoIterator<Item = &'static str>) -> TsRouter {
209231
let mut router = TsRouter::new();
210232
for handler in handlers {
211-
router.add_handler(handler, &[] as &[&str], &|| {});
233+
router.add_handler(
234+
&HandlerMeta {
235+
name: handler,
236+
param_names: &[],
237+
kind: HandlerKind::Query,
238+
},
239+
&|| {},
240+
);
212241
}
213242
router
214243
}
215244

216245
#[rstest]
217246
#[case::empty(make_router([]), "{ }")]
218-
#[case::shallow(make_router(["handler"]), "{ handler: () => null, }")]
219-
#[case::multi(make_router(["handler_a", "handler_b"]), "{ handler_a: () => null, handler_b: () => null, }")]
247+
#[case::shallow(make_router(["handler"]), "{ handler: Query<[], null>, }")]
248+
#[case::multi(make_router(["handler_a", "handler_b"]), "{ handler_a: Query<[], null>, handler_b: Query<[], null>, }")]
220249
#[case::deep(
221250
{
222251
let mut module = make_router(["top"]);
@@ -227,7 +256,7 @@ mod test {
227256
});
228257
module
229258
},
230-
"{ layer_2: { layer_3: { inner: () => null, }, middle: () => null, }, top: () => null, }"
259+
"{ layer_2: { layer_3: { inner: Query<[], null>, }, middle: Query<[], null>, }, top: Query<[], null>, }"
231260
)]
232261
fn nested(#[case] router: TsRouter, #[case] expected: &str) {
233262
assert_eq!(router.get_router_type(), expected);
@@ -238,18 +267,32 @@ mod test {
238267
#![allow(unused)]
239268

240269
let mut router = TsRouter::new();
241-
router.add_handler("outer", &["user_type"], &|ctx: (), user_type: UserTypeA| {});
270+
router.add_handler(
271+
&HandlerMeta {
272+
name: "outer",
273+
param_names: &["user_type"],
274+
kind: HandlerKind::Query,
275+
},
276+
&|ctx: (), user_type: UserTypeA| {},
277+
);
242278
router.nest("nested", {
243279
let mut router = TsRouter::new();
244-
router.add_handler("inner", &["user_type"], &|ctx: (), user_type: UserTypeB| {});
280+
router.add_handler(
281+
&HandlerMeta {
282+
name: "inner",
283+
param_names: &["user_type"],
284+
kind: HandlerKind::Query,
285+
},
286+
&|ctx: (), user_type: UserTypeB| {},
287+
);
245288
router
246289
});
247290

248291
assert_eq!(
249292
router.generate_typescript(),
250293
r#"type UserTypeB = string;
251294
type UserTypeA = { a: number, b: boolean, };
252-
export type Router = { nested: { inner: (user_type: UserTypeB) => null, }, outer: (user_type: UserTypeA) => null, };
295+
export type Router = { nested: { inner: Query<[user_type: UserTypeB], null>, }, outer: Query<[user_type: UserTypeA], null>, };
253296
"#
254297
);
255298
}

tests/e2e.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use qubit::ts::router::Router;
22

3-
#[qubit::handler2(query)]
3+
#[qubit::handler(query)]
44
fn cool_handler() -> u32 {
55
123
66
}
77

8-
#[qubit::handler2(query)]
8+
#[qubit::handler(query)]
99
fn even_cool_handler() -> u32 {
1010
456
1111
}
@@ -17,6 +17,4 @@ fn main() {
1717
.handler(even_cool_handler);
1818

1919
println!("{}", router.generate_type_to_string());
20-
21-
panic!()
2220
}

tests/handlers.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![allow(unused_variables)]
22

3-
use qubit::*;
3+
use qubit::{handler, ts::router::Router};
44

55
macro_rules! test_handler {
66
($handler:ident = $kind:ident<[$($params:tt)*], $ret:tt>) => {
@@ -16,14 +16,18 @@ macro_rules! test_handler {
1616
};
1717

1818
($handler:ident <$ctx:ty> ($handler_name:ident) = $kind:ident<[$($params:tt)*], $ret:tt>) => {
19-
let ty = <$handler as Handler<$ctx>>::get_type();
19+
let ty = Router::new().handler($handler).generate_type_to_string();
2020

21-
assert_eq!(ty.name, stringify!($handler_name));
2221
assert_eq!(
23-
ty.signature,
24-
concat!(stringify!($kind), "<[", stringify!($($params)*), "], ", stringify!($ret), ">")
22+
ty,
23+
format!(
24+
"export type Router = {{ {handler_name}: {kind}<[{params}], {ret}>, }};\n",
25+
handler_name = stringify!($handler_name),
26+
kind = stringify!($kind),
27+
params = stringify!($($params)*),
28+
ret = stringify!($ret),
29+
)
2530
);
26-
assert_eq!(ty.kind, stringify!($kind));
2731
};
2832
}
2933

0 commit comments

Comments
 (0)