mrpc/templates/typescript_client.rs.ts

82 lines
2.3 KiB
TypeScript

@use itertools::Itertools;
@use crate::data::RPC;
@use crate::generators::ts_c::*;
@(rpc: &RPC)
@for e in &rpc.enums {
export enum @e.name @{
@for (k,v) in &e.values { @k = @v,
}
@}
}
@for s in &rpc.structs {
export interface @s.name @{
@for f in &s.fields { @f.name: @ty_to_str(&f.ty);
}
@}
}
interface _WSResponse @{
id: number;
data: any;
@}
interface _WSWaitingEntry @{
ok: (v: any) => void;
err: (reason?: any) => void;
@}
export class MRPCConnector @{
url: string;
socket: WebSocket;
nmi: number;
waiting: @{ [id: number]: _WSWaitingEntry @};
streams: @{ [id: number]: (v: any) => void @};
private open() @{
this.socket = new WebSocket(this.url);
this.socket.onmessage = ev => @{
const data = JSON.parse(ev.data) as _WSResponse;
if (data.id in this.streams) @{
this.streams[data.id](data.data);
if (data.data == null)
delete this.streams[data.id];
@} else if (data.id in this.waiting) @{
this.waiting[data.id].ok(data.data);
delete this.waiting[data.id];
@} else @{
console.log(`Got unexpected message: $@{data@}`);
@}
@}
this.socket.onerror = () => setTimeout(() => @{this.open();@}, 2500);
this.socket.onclose = () => setTimeout(() => @{this.open();@}, 2500);
@}
private get_prom<T>(id: number): Promise<T> @{
return new Promise<T>((ok, err) => @{ this.waiting[id] = @{ok, err@}; @});
@}
public constructor(url: string) @{
this.url = url;
this.nmi = 0;
this.waiting = @{@};
this.streams = @{@};
this.open();
@}
@for s in &rpc.services { @for m in &s.methods {
public @(s.name)_@(m.name)(@method_args(m))@method_ret(m) @{
const __msg = @{
id: this.nmi++,
service: '@s.name',
method: '@m.name',
data: @{@m.args.iter().map(|a| &a.name).join(",")@}
@};
@if m.ret.is_some() && !m.ret_stream {const __p = this.get_prom<@ty_to_str(m.ret.as_ref().unwrap())>(__msg.id);}
else if m.ret_stream {this.streams[__msg.id] = __cbk;}
this.socket.send(JSON.stringify(__msg));
@if m.ret.is_some() && !m.ret_stream {return __p;}
@}
}}
@}