mirror of
https://github.com/roleypoly/roleypoly-v1.git
synced 2025-04-25 12:19:10 +00:00
106 lines
2.4 KiB
JavaScript
106 lines
2.4 KiB
JavaScript
// @flow
|
|
import superagent from 'superagent'
|
|
import RPCError from '../../rpc/_error'
|
|
|
|
export type RPCResponse = {
|
|
response?: mixed,
|
|
hash?: string,
|
|
|
|
// error stuff
|
|
error?: boolean,
|
|
msg?: string,
|
|
trace?: string
|
|
}
|
|
|
|
export type RPCRequest = {
|
|
fn: string,
|
|
args: mixed[]
|
|
}
|
|
|
|
export default class RPCClient {
|
|
dev: boolean = false
|
|
baseUrl: string
|
|
firstKnownHash: string
|
|
recentHash: string
|
|
|
|
rpc: {
|
|
[fn: string]: (...args: any[]) => Promise<mixed> | string
|
|
} = {}
|
|
|
|
__rpcAvailable: Array<{
|
|
name: string,
|
|
args: number
|
|
}> = []
|
|
|
|
constructor ({ forceDev, baseUrl = '/api/_rpc' }: { forceDev?: boolean, baseUrl?: string } = {}) {
|
|
this.baseUrl = (process.env.APP_URL || '') + baseUrl
|
|
|
|
if (forceDev != null) {
|
|
this.dev = forceDev
|
|
} else {
|
|
this.dev = process.env.NODE_ENV === 'development'
|
|
}
|
|
|
|
this.rpc = new Proxy({
|
|
toJSON () {
|
|
return '{}'
|
|
}
|
|
}, { get: this.__rpcCall, has: this.__checkCall, ownKeys: this.__listCalls, delete: () => {} })
|
|
|
|
if (this.dev) {
|
|
this.updateCalls()
|
|
}
|
|
}
|
|
|
|
async updateCalls () {
|
|
// this is for development only. doing in prod is probably dumb.
|
|
const rsp = await superagent.get(this.baseUrl)
|
|
if (rsp.status !== 200) {
|
|
console.error(rsp)
|
|
return
|
|
}
|
|
|
|
const { hash, available } = rsp.body
|
|
|
|
this.__rpcAvailable = available
|
|
if (this.firstKnownHash == null) {
|
|
this.firstKnownHash = hash
|
|
}
|
|
|
|
this.recentHash = hash
|
|
|
|
// just kinda prefill. none of these get called anyway.
|
|
// and don't matter in prod either.
|
|
for (let { name } of available) {
|
|
this.rpc[name] = async () => {}
|
|
}
|
|
}
|
|
|
|
async call (fn: string, ...args: any[]): mixed {
|
|
const req: RPCRequest = { fn, args }
|
|
const rsp = await superagent.post(this.baseUrl).send(req).ok(() => true)
|
|
const body: RPCResponse = rsp.body
|
|
if (body.error === true) {
|
|
throw RPCError.fromResponse(body, rsp.status)
|
|
}
|
|
|
|
if (body.hash != null) {
|
|
if (this.firstKnownHash == null) {
|
|
this.firstKnownHash = body.hash
|
|
}
|
|
|
|
this.recentHash = body.hash
|
|
|
|
if (this.firstKnownHash !== this.recentHash) {
|
|
this.updateCalls()
|
|
}
|
|
}
|
|
|
|
return body.response
|
|
}
|
|
|
|
// PROXY HANDLERS
|
|
__rpcCall = (_: {}, fn: string) => this.call.bind(this, fn)
|
|
__checkCall = (_: {}, fn: string) => this.dev ? this.__listCalls(_).includes(fn) : true
|
|
__listCalls = (_: {}): string[] => this.__rpcAvailable.map(x => x.name)
|
|
}
|