82 lines
2.3 KiB
TypeScript
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;}
|
||
|
@}
|
||
|
}}
|
||
|
@}
|