Skip to content

Commit 33aed5c

Browse files
committed
feat(reactive-rpc): 🎸 add type safety to emulated E2E client
1 parent 070c4c9 commit 33aed5c

File tree

3 files changed

+22
-12
lines changed

3 files changed

+22
-12
lines changed

src/reactive-rpc/common/testing/buildE2eClient.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ import {ConnectionContext} from '../../server/context';
55
import {RpcCodecs} from '../codec/RpcCodecs';
66
import {RpcMessageCodecs} from '../codec/RpcMessageCodecs';
77
import {ReactiveRpcClientMessage, ReactiveRpcMessage, ReactiveRpcServerMessage} from '../messages';
8-
import {RpcClient, RpcMessageStreamProcessor, StreamingRpcClient} from '../rpc';
9-
import type {RpcCaller} from '../rpc/caller/RpcCaller';
8+
import {RpcMessageStreamProcessor, StreamingRpcClient, TypedRpcClient} from '../rpc';
9+
import type {FunctionStreamingType, FunctionType} from '../../../json-type/type/classes';
10+
import type {Observable} from 'rxjs';
11+
import type {ResolveType} from '../../../json-type';
12+
import type {TypeRouter} from '../../../json-type/system/TypeRouter';
13+
import type {TypeRouterCaller} from '../rpc/caller/TypeRouterCaller';
1014

1115
export interface BuildE2eClientOptions {
12-
caller: RpcCaller;
13-
1416
/**
1517
* Writer to use for encoding messages. Defaults to `new Writer(4 * 1024)`.
1618
*/
@@ -76,8 +78,7 @@ export interface BuildE2eClientOptions {
7678
token?: string;
7779
}
7880

79-
export const buildE2eClient = <T = RpcClient>(opt: BuildE2eClientOptions) => {
80-
const caller = opt.caller;
81+
export const buildE2eClient = <Caller extends TypeRouterCaller<any>>(caller: Caller, opt: BuildE2eClientOptions) => {
8182
const writer = opt.writer ?? new Writer(Fuzzer.randomInt2(opt.writerDefaultBufferKb ?? [4, 4]) * 1024);
8283
const codecs = new RpcCodecs(new Codecs(writer), new RpcMessageCodecs());
8384
const ctx = new ConnectionContext(
@@ -115,8 +116,19 @@ export const buildE2eClient = <T = RpcClient>(opt: BuildE2eClientOptions) => {
115116
bufferSize: Fuzzer.randomInt2(opt.clientBufferSize ?? [1, 1]),
116117
bufferTime: Fuzzer.randomInt2(opt.clientBufferTime ?? [0, 0]),
117118
});
118-
const typedClient = client as T;
119+
type Router = UnTypeRouterCaller<Caller>;
120+
type Routes = UnTypeRouter<Router>;
121+
type Methods = {[K in keyof Routes]: UnwrapFunction<Routes[K]>};
122+
const typedClient = client as TypedRpcClient<Methods>;
119123
return {
120124
client: typedClient,
121125
};
122126
};
127+
128+
type UnTypeRouterCaller<T> = T extends TypeRouterCaller<infer R> ? R : never;
129+
type UnTypeRouter<T> = T extends TypeRouter<infer R> ? R : never;
130+
type UnwrapFunction<F> = F extends FunctionType<infer Req, infer Res>
131+
? (req: ResolveType<Req>) => Promise<ResolveType<Res>>
132+
: F extends FunctionStreamingType<infer Req, infer Res>
133+
? (req$: Observable<ResolveType<Req>>) => Observable<ResolveType<Res>>
134+
: never;

src/server/__tests__/setup.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,9 @@ import {Services} from '../services/Services';
44

55
export const setup = () => {
66
const services = new Services();
7-
const caller = createCaller(services);
7+
const {caller} = createCaller(services);
88
const call = caller.callSimple.bind(caller);
9-
// const {client} = buildE2eClient<TypedRpcClient<{}>>({caller});
10-
const {client} = buildE2eClient({
11-
caller,
9+
const {client} = buildE2eClient(caller, {
1210
writerDefaultBufferKb: [1, 32],
1311
clientBufferSize: [1, 3],
1412
clientBufferTime: [1, 10],

src/server/routes/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@ export const createCaller = (services: Services) => {
2525
return RpcError.valueFrom(error);
2626
},
2727
});
28-
return caller;
28+
return {router, caller};
2929
};

0 commit comments

Comments
 (0)