import {as_id} from '../../code/as_pkt.jsy' import {rx_rpc} from './rpc_api.jsy' import {RPC_Error} from './rpc_error.jsy' export const rpc_client = /* #__PURE__ */ Object.create @ @{} with(kw) :: return @{} __proto__: this, ...kw to(id, meta, kw) :: id = as_id(id) if id :: kw = @{} ... kw, id if null != meta :: kw.meta = meta return this.with(kw) ms_timeout: 1000 absent: {timeout: true, err: 'timeout'} with_opt(opt) :: if 'number' === typeof opt :: opt = {ms_timeout: opt} return this.with(opt) async rpc_post(method, ...args) :: return this._rpc_v(method, null, args) async rpc_query(method, ...args) :: let xtgt = this.tgt_router.addOnce @ this.ms_timeout, this.absent await this._rpc_v(method, xtgt.id, args) return xtgt.promise.then(this._rpc_reply) _rpc_reply(o) :: if o.err :: throw RPC_Error.from(o) return o.ok _rpc_v(method, id_reply, args_v) :: let {id, meta} = this if ! id :: throw new Error('Invalid RPC destination') let body = @[] '!', id_reply, method, ...args_v return this.tgt_router.send @ id, meta, body @{} post: _wm_rpc_pxy('rpc_post') query: _wm_rpc_pxy('rpc_query') function _wm_rpc_pxy(name) :: // Object attribute for weak-ref caching of proxies and methods let wm = new WeakMap() return @{} get() :: // object attribute getter let r = wm.get(this) if undefined === r :: // weakly cache proxy wm.set(this, r=_rpc_pxy({}, this, this[name])) return r function _rpc_pxy(obj, host, wrap_fn) :: return new Proxy @ obj, @{} get(obj, method) :: // proxy attribute getter let r = obj[method] if undefined === r && rx_rpc.test(method) :: // cache bound method obj[method] = r = wrap_fn.bind(host, method) return r