fix(rpc): separate public calls + better pending handlers

This commit is contained in:
2026-09-28 02:05:40 +01:00
parent 6247b7d781
commit c085fd2c8f
5 changed files with 22 additions and 8 deletions
+2 -1
View File
@@ -51,6 +51,7 @@ export class RPCInstanceBase {
to: RPCEnvironment, to: RPCEnvironment,
args: unknown[], args: unknown[],
player: number | null, player: number | null,
type: 'event' | 'broadcast' = 'event',
): RPCState { ): RPCState {
return { return {
event, event,
@@ -60,7 +61,7 @@ export class RPCInstanceBase {
error: null, error: null,
data: args, data: args,
player, player,
type: 'event', type,
} }
} }
+8 -1
View File
@@ -54,11 +54,18 @@ export class RPCInstanceClient extends RPCInstanceBase {
const payload = this.accept(payloadRaw) const payload = this.accept(payloadRaw)
if (!payload) return if (!payload) return
if (payload.type === 'event') { if (payload.type === 'event' || payload.type === 'broadcast') {
if (payload.calledTo === 'client') { if (payload.calledTo === 'client') {
const response = await this.dispatch(this._emitterServer, payload) const response = await this.dispatch(this._emitterServer, payload)
if (payload.type === 'event') {
emitNet(RPCEvents.LISTENER_CLIENT, stringify(response)) emitNet(RPCEvents.LISTENER_CLIENT, stringify(response))
} else if (response.error) {
// nobody waits for a broadcast, so its failures only show up here
this.log(
`broadcast ${payload.event} failed: ${response.error.message}`,
)
}
} }
if (payload.calledTo === 'webview') { if (payload.calledTo === 'webview') {
this._sendWebMessage({ this._sendWebMessage({
+2 -2
View File
@@ -61,7 +61,7 @@ export class RPCInstanceServer extends RPCInstanceBase {
if (payload.type === 'event') { if (payload.type === 'event') {
const response = await this.dispatch(emitter, payload, player) const response = await this.dispatch(emitter, payload, player)
emitNet(RPCEvents.LISTENER_SERVER, player, stringify(response)) emitNet(RPCEvents.LISTENER_SERVER, player, stringify(response))
} else { } else if (payload.type === 'response') {
this.settle(payload, player) this.settle(payload, player)
} }
} }
@@ -108,7 +108,7 @@ export class RPCInstanceServer extends RPCInstanceBase {
EventName extends keyof s.RPCEvents_ServerClient, EventName extends keyof s.RPCEvents_ServerClient,
Arguments extends Parameters<s.RPCEvents_ServerClient[EventName]>, Arguments extends Parameters<s.RPCEvents_ServerClient[EventName]>,
>(eventName: EventName, ...args: Arguments): Promise<void> { >(eventName: EventName, ...args: Arguments): Promise<void> {
const payload = this.request(eventName, 'client', args, -1) const payload = this.request(eventName, 'client', args, -1, 'broadcast')
emitNet(RPCEvents.LISTENER_SERVER, -1, stringify(payload)) emitNet(RPCEvents.LISTENER_SERVER, -1, stringify(payload))
} }
+1 -1
View File
@@ -24,7 +24,7 @@ export function isRPCState(value: unknown): value is RPCState {
return ( return (
typeof v.event === 'string' && typeof v.event === 'string' &&
typeof v.uuid === 'string' && typeof v.uuid === 'string' &&
(v.type === 'event' || v.type === 'response') && (v.type === 'event' || v.type === 'response' || v.type === 'broadcast') &&
ENVIRONMENTS.includes(v.calledFrom) && ENVIRONMENTS.includes(v.calledFrom) &&
ENVIRONMENTS.includes(v.calledTo) && ENVIRONMENTS.includes(v.calledTo) &&
(v.data === null || Array.isArray(v.data)) (v.data === null || Array.isArray(v.data))
+8 -2
View File
@@ -33,8 +33,14 @@ export type RPCConfig<T extends RPCEnvironment | unknown> = {
timeout?: number timeout?: number
} }
/** **Internal** */ /**
export type RPCEventType = 'event' | 'response' * **Internal**
*
* - `event`: call that expects a `response`
* - `response`: answer to an `event`
* - `broadcast`: one-way event, receivers do not reply
*/
export type RPCEventType = 'event' | 'response' | 'broadcast'
/** /**
* **Internal** * **Internal**