chore(rpc): promote Wrapper to BaseInstance

This commit is contained in:
2026-09-28 02:05:40 +01:00
parent 571d113386
commit 558f04567a
6 changed files with 156 additions and 367 deletions
@@ -1,9 +1,10 @@
import { Emitter } from '../utils/emitter'
import { Emitter, type Handler } from '../utils/emitter'
import {
handlerErrorMessage,
notRegisteredMessage,
RPCError,
} from '../utils/errors'
import { generateUUID } from '../utils/funcs'
import { Pending } from '../utils/pending'
import {
type RPCConfig,
@@ -12,21 +13,84 @@ import {
type RPCState,
} from '../utils/types'
export class Wrapper {
protected env: RPCEnvironment
protected _emitterLocal: Emitter
protected _pending: Pending
protected debug: boolean
protected console: Console
/** Shared plumbing of the server, client and webview instances */
export class RPCInstanceBase {
protected readonly env: RPCEnvironment
protected readonly debug: boolean
protected readonly _emitterLocal = new Emitter()
protected readonly _pending: Pending
constructor(cfg: RPCConfig<RPCEnvironment>) {
this.env = cfg.env
this._emitterLocal = new Emitter()
this._pending = new Pending(cfg.timeout ?? 5000)
this.debug = cfg.debug ?? false
this.console = console
this._pending = new Pending(cfg.timeout ?? 5000)
}
// ===== LISTENERS =====
/** Registers `cb` for `event` on `emitter`; `method` is only used for logs */
protected listen(
emitter: Emitter,
method: string,
event: string,
cb: Handler,
): this {
this.log(`${method} ${event}`)
emitter.on(event, cb)
return this
}
protected unlisten(emitter: Emitter, method: string, event: string): this {
this.log(`${method} ${event}`)
emitter.off(event)
return this
}
// ===== OUTGOING =====
/** Builds an event payload sent from this environment to `to` */
protected request(
event: string,
to: RPCEnvironment,
args: unknown[],
player: number | null,
): RPCState {
return {
event,
uuid: generateUUID(),
calledFrom: this.env,
calledTo: to,
error: null,
data: args,
player,
type: 'event',
}
}
/** Calls a listener registered with `onSelf` in this environment */
protected emitLocal<R>(event: string, args: unknown[]): Promise<R> {
this.log(`emitSelf ${event}`)
if (!this._emitterLocal.has(event)) {
throw new RPCError(
RPCErrors.EVENT_NOT_REGISTERED,
notRegisteredMessage(event, this.env, this.env),
{ event, uuid: '', from: this.env, to: this.env },
)
}
return this._emitterLocal.emit<R>(event, ...args)
}
/** Settles the call waiting for `response`; ignores late or unexpected ones */
protected settle(response: RPCState): void {
const found = response.error
? this._pending.reject(response.uuid, RPCError.fromResponse(response))
: this._pending.resolve(response.uuid, response.data?.[0])
if (!found) this.logIgnored(response)
}
// ===== INCOMING =====
/**
* Runs the listener for `request` and builds the response to send back.
* Never throws: a missing listener or a thrown error ends up in `error`.
@@ -57,7 +121,7 @@ export class Wrapper {
return this.response(request, [data], null)
} catch (e) {
// keep the stack visible where the listener lives
this.console.error(e)
console.error(e)
return this.errorResponse(
request,
new RPCError(
@@ -83,32 +147,17 @@ export class Wrapper {
})
}
/** Settles the call waiting for `response`; ignores late or unexpected ones */
protected settle(response: RPCState): void {
const found = response.error
? this._pending.reject(response.uuid, RPCError.fromResponse(response))
: this._pending.resolve(response.uuid, response.data?.[0])
// ===== LOGS =====
if (!found) this.logIgnored(response)
}
/** Throws if no local listener is registered for `event` */
protected assertListener(emitter: Emitter, event: string): void {
if (!emitter.has(event)) {
throw new RPCError(
RPCErrors.EVENT_NOT_REGISTERED,
notRegisteredMessage(event, this.env, this.env),
{ event, uuid: '', from: this.env, to: this.env },
)
}
/** Debug-only log, prefixed with the environment */
protected log(message: string): void {
if (this.debug) console.log(`[RPC]:${this.env}:${message}`)
}
protected logIgnored(response: RPCState): void {
if (this.debug) {
this.console.log(
`[RPC]:ignored response ${response.event} ${response.uuid} (no pending call, possibly timed out)`,
)
}
this.log(
`ignored response ${response.event} ${response.uuid} (no pending call, possibly timed out)`,
)
}
private response(
+28 -111
View File
@@ -2,7 +2,7 @@ import type * as s from '@entityseven/fivem-rpc-shared-types'
import { Emitter } from '../utils/emitter'
import { RPCError } from '../utils/errors'
import { generateUUID, parse, stringify, stringifyWeb } from '../utils/funcs'
import { parse, stringify, stringifyWeb } from '../utils/funcs'
import {
NATIVE_CLIENT_EVENTS,
NATIVE_CLIENT_NETWORK_EVENTS,
@@ -17,9 +17,9 @@ import {
type RPCStateRaw,
type RPCStateWeb,
} from '../utils/types'
import { Wrapper } from './wrapper'
import { RPCInstanceBase } from './base'
export class RPCInstanceClient extends Wrapper {
export class RPCInstanceClient extends RPCInstanceBase {
private readonly _emitterServer: Emitter
private readonly _emitterWeb: Emitter
@@ -29,7 +29,7 @@ export class RPCInstanceClient extends Wrapper {
this._emitterServer = new Emitter()
this._emitterWeb = new Emitter()
this.console.log('[RPC] Initialized Client')
console.log('[RPC] Initialized Client')
onNet(RPCEvents.LISTENER_SERVER, this._handleServer.bind(this))
RegisterNuiCallbackType(RPCEvents.LISTENER_WEB)
@@ -55,11 +55,9 @@ export class RPCInstanceClient extends Wrapper {
}
const payload = parse(payloadRaw)
if (this.debug) {
this.console.log(
`[RPC]:client:accepted ${payload.type} ${payload.event} from ${payload.calledFrom}`,
)
}
this.log(
`accepted ${payload.type} ${payload.event} from ${payload.calledFrom}`,
)
if (payload.type === 'event') {
if (payload.calledTo === 'client') {
@@ -88,11 +86,9 @@ export class RPCInstanceClient extends Wrapper {
}
private async _handleWeb(payload: RPCState): Promise<unknown> {
if (this.debug) {
this.console.log(
`[RPC]:client:accepted ${payload.type} ${payload.event} from ${payload.calledFrom}`,
)
}
this.log(
`accepted ${payload.type} ${payload.event} from ${payload.calledFrom}`,
)
if (payload.type === 'event') {
if (payload.calledTo === 'client') {
@@ -134,25 +130,13 @@ export class RPCInstanceClient extends Wrapper {
...args: CallbackArguments
) => Awaited<CallbackReturn> | Promise<Awaited<CallbackReturn>>,
): this {
if (this.debug) {
this.console.log(`[RPC]:onServer ${eventName}`)
}
this._emitterServer.on(eventName, cb)
return this
return this.listen(this._emitterServer, 'onServer', eventName, cb)
}
public offServer<EventName extends keyof s.RPCEvents_ServerClient>(
eventName: EventName,
): this {
if (this.debug) {
this.console.log(`[RPC]:offServer ${eventName}`)
}
this._emitterServer.off(eventName)
return this
return this.unlisten(this._emitterServer, 'offServer', eventName)
}
public async emitServer<
@@ -160,16 +144,12 @@ export class RPCInstanceClient extends Wrapper {
Arguments extends Parameters<s.RPCEvents_ClientServer[EventName]>,
Response extends ReturnType<s.RPCEvents_ClientServer[EventName]>,
>(eventName: EventName, ...args: Arguments): Promise<Awaited<Response>> {
const payload: RPCState = {
event: eventName,
uuid: generateUUID(),
calledFrom: 'client',
calledTo: 'server',
error: null,
data: args.length ? args : null,
player: GetPlayerServerId(PlayerId()),
type: 'event',
}
const payload = this.request(
eventName,
'server',
args,
GetPlayerServerId(PlayerId()),
)
emitNet(RPCEvents.LISTENER_CLIENT, stringify(payload))
@@ -188,25 +168,13 @@ export class RPCInstanceClient extends Wrapper {
...args: CallbackArguments
) => Awaited<CallbackReturn> | Promise<Awaited<CallbackReturn>>,
): this {
if (this.debug) {
this.console.log(`[RPC]:onWebview ${eventName}`)
}
this._emitterWeb.on(eventName, cb)
return this
return this.listen(this._emitterWeb, 'onWebview', eventName, cb)
}
public offWebview<EventName extends keyof s.RPCEvents_WebviewClient>(
eventName: EventName,
): this {
if (this.debug) {
this.console.log(`[RPC]:offWebview ${eventName}`)
}
this._emitterWeb.off(eventName)
return this
return this.unlisten(this._emitterWeb, 'offWebview', eventName)
}
public async emitWebview<
@@ -214,16 +182,7 @@ export class RPCInstanceClient extends Wrapper {
Arguments extends Parameters<s.RPCEvents_ClientWebview[EventName]>,
Response extends ReturnType<s.RPCEvents_ClientWebview[EventName]>,
>(eventName: EventName, ...args: Arguments): Promise<Awaited<Response>> {
const payload: RPCState = {
event: eventName,
uuid: generateUUID(),
calledFrom: 'client',
calledTo: 'webview',
error: null,
data: args.length ? args : null,
player: PlayerId(),
type: 'event',
}
const payload = this.request(eventName, 'webview', args, PlayerId())
this._sendWebMessage({
origin: RPCEvents.LISTENER_CLIENT,
@@ -245,25 +204,13 @@ export class RPCInstanceClient extends Wrapper {
...args: CallbackArguments
) => Awaited<CallbackReturn> | Promise<Awaited<CallbackReturn>>,
): this {
if (this.debug) {
this.console.log(`[RPC]:onSelf ${eventName}`)
}
this._emitterLocal.on(eventName, cb)
return this
return this.listen(this._emitterLocal, 'onSelf', eventName, cb)
}
public offSelf<EventName extends keyof s.RPCEvents_Client>(
eventName: EventName,
): this {
if (this.debug) {
this.console.log(`[RPC]:offSelf ${eventName}`)
}
this._emitterLocal.off(eventName)
return this
return this.unlisten(this._emitterLocal, 'offSelf', eventName)
}
public async emitSelf<
@@ -271,29 +218,7 @@ export class RPCInstanceClient extends Wrapper {
Arguments extends Parameters<s.RPCEvents_Client[EventName]>,
Response extends ReturnType<s.RPCEvents_Client[EventName]>,
>(eventName: EventName, ...args: Arguments): Promise<Awaited<Response>> {
const payload: RPCState = {
event: eventName,
uuid: generateUUID(),
calledFrom: 'client',
calledTo: 'client',
error: null,
data: args.length ? args : null,
player: null,
type: 'event',
}
if (this.debug) {
this.console.log(
`[RPC]:accepted ${payload.event} from ${payload.calledFrom}`,
)
}
this.assertListener(this._emitterLocal, payload.event)
return await this._emitterLocal.emit<Awaited<Response>>(
payload.event,
...(payload.data && payload.data.length > 0 ? payload.data : []),
)
return this.emitLocal<Awaited<Response>>(eventName, args)
}
// ===== OTHER =====
@@ -305,9 +230,7 @@ export class RPCInstanceClient extends Wrapper {
command: CommandName,
cb: (player: number, args: CallbackArguments, commandRaw: string) => void,
): this {
if (this.debug) {
this.console.log(`[RPC]:onCommand ${command}`)
}
this.log(`onCommand ${command}`)
RegisterCommand(command, cb, false)
@@ -322,9 +245,7 @@ export class RPCInstanceClient extends Wrapper {
throw new RPCError(RPCErrors.UNKNOWN_NATIVE, RPCErrors.UNKNOWN_NATIVE)
}
if (this.debug) {
this.console.log(`[RPC]:onNativeEvent ${eventName}`)
}
this.log(`onNativeEvent ${eventName}`)
on(eventName, cb)
@@ -341,9 +262,7 @@ export class RPCInstanceClient extends Wrapper {
throw new RPCError(RPCErrors.UNKNOWN_NATIVE, RPCErrors.UNKNOWN_NATIVE)
}
if (this.debug) {
this.console.log(`[RPC]:onNativeNetworkEvent ${eventName}`)
}
this.log(`onNativeNetworkEvent ${eventName}`)
on(eventName, cb)
@@ -351,9 +270,7 @@ export class RPCInstanceClient extends Wrapper {
}
public setWebviewFocus(hasFocus: boolean, hasCursor: boolean): this {
if (this.debug) {
this.console.log(`[RPC]:setWebviewFocus ${hasFocus} ${hasCursor}`)
}
this.log(`setWebviewFocus ${hasFocus} ${hasCursor}`)
SetNuiFocus(hasFocus, hasCursor)
+24 -118
View File
@@ -2,19 +2,18 @@ import type * as s from '@entityseven/fivem-rpc-shared-types'
import { Emitter } from '../utils/emitter'
import { RPCError } from '../utils/errors'
import { generateUUID, parse, stringify } from '../utils/funcs'
import { parse, stringify } from '../utils/funcs'
import { NATIVE_SERVER_EVENTS } from '../utils/native'
import {
type RPCConfig,
RPCErrors,
RPCEvents,
type RPCNativeServerEvents,
type RPCState,
type RPCStateRaw,
} from '../utils/types'
import { Wrapper } from './wrapper'
import { RPCInstanceBase } from './base'
export class RPCInstanceServer extends Wrapper {
export class RPCInstanceServer extends RPCInstanceBase {
private readonly _emitterClient: Emitter
private readonly _emitterWeb: Emitter
@@ -24,7 +23,7 @@ export class RPCInstanceServer extends Wrapper {
this._emitterClient = new Emitter()
this._emitterWeb = new Emitter()
this.console.log('[RPC] Initialized Server')
console.log('[RPC] Initialized Server')
onNet(RPCEvents.LISTENER_CLIENT, this._handleClient.bind(this))
onNet(RPCEvents.LISTENER_WEB, this._handleWeb.bind(this))
@@ -40,17 +39,15 @@ export class RPCInstanceServer extends Wrapper {
}
const payload = parse(payloadRaw)
if (this.debug) {
this.console.log(
`[RPC]:server:accepted ${payload.type} ${payload.event} from ${payload.calledFrom}`,
)
}
this.log(
`accepted ${payload.type} ${payload.event} from ${payload.calledFrom}`,
)
if (payload.calledFrom === 'client') {
if (payload.type === 'event') {
if (payload.player === null || payload.player === -1) {
// nobody to reply to, the caller times out
this.console.error(
console.error(
new RPCError(
RPCErrors.NO_PLAYER,
`${RPCErrors.NO_PLAYER}: "${payload.event}" from ${payload.calledFrom}`,
@@ -81,17 +78,15 @@ export class RPCInstanceServer extends Wrapper {
}
const payload = parse(payloadRaw)
if (this.debug) {
this.console.log(
`[RPC]:server:accepted ${payload.type} ${payload.event} from ${payload.calledFrom}`,
)
}
this.log(
`accepted ${payload.type} ${payload.event} from ${payload.calledFrom}`,
)
if (payload.calledFrom === 'webview') {
if (payload.type === 'event') {
if (payload.player === null || payload.player === -1) {
// nobody to reply to, the caller times out
this.console.error(
console.error(
new RPCError(
RPCErrors.NO_PLAYER,
`${RPCErrors.NO_PLAYER}: "${payload.event}" from ${payload.calledFrom}`,
@@ -127,25 +122,13 @@ export class RPCInstanceServer extends Wrapper {
...args: CallbackArguments
) => Awaited<CallbackReturn> | Promise<Awaited<CallbackReturn>>,
): this {
if (this.debug) {
this.console.log(`[RPC]:onClient ${eventName}`)
}
this._emitterClient.on(eventName, cb)
return this
return this.listen(this._emitterClient, 'onClient', eventName, cb)
}
public offClient<EventName extends keyof s.RPCEvents_ClientServer>(
eventName: EventName,
): this {
if (this.debug) {
this.console.log(`[RPC]:offClient ${eventName}`)
}
this._emitterClient.off(eventName)
return this
return this.unlisten(this._emitterClient, 'offClient', eventName)
}
public async emitClient<
@@ -157,16 +140,7 @@ export class RPCInstanceServer extends Wrapper {
eventName: EventName,
...args: Arguments
): Promise<Awaited<Response>> {
const payload: RPCState = {
event: eventName,
uuid: generateUUID(),
calledFrom: 'server',
calledTo: 'client',
error: null,
data: args.length ? args : null,
player: player,
type: 'event',
}
const payload = this.request(eventName, 'client', args, player)
emitNet(RPCEvents.LISTENER_SERVER, player, stringify(payload))
@@ -177,16 +151,7 @@ export class RPCInstanceServer extends Wrapper {
EventName extends keyof s.RPCEvents_ServerClient,
Arguments extends Parameters<s.RPCEvents_ServerClient[EventName]>,
>(eventName: EventName, ...args: Arguments): Promise<void> {
const payload: RPCState = {
event: eventName,
uuid: generateUUID(),
calledFrom: 'server',
calledTo: 'client',
error: null,
data: args.length ? args : null,
player: -1,
type: 'event',
}
const payload = this.request(eventName, 'client', args, -1)
emitNet(RPCEvents.LISTENER_SERVER, -1, stringify(payload))
}
@@ -204,25 +169,13 @@ export class RPCInstanceServer extends Wrapper {
...args: CallbackArguments
) => Awaited<CallbackReturn> | Promise<Awaited<CallbackReturn>>,
): this {
if (this.debug) {
this.console.log(`[RPC]:onWebview ${eventName}`)
}
this._emitterWeb.on(eventName, cb)
return this
return this.listen(this._emitterWeb, 'onWebview', eventName, cb)
}
public offWebview<EventName extends keyof s.RPCEvents_WebviewServer>(
eventName: EventName,
): this {
if (this.debug) {
this.console.log(`[RPC]:offWebview ${eventName}`)
}
this._emitterWeb.off(eventName)
return this
return this.unlisten(this._emitterWeb, 'offWebview', eventName)
}
public async emitWebview<
@@ -234,16 +187,7 @@ export class RPCInstanceServer extends Wrapper {
eventName: EventName,
...args: Arguments
): Promise<Awaited<Response>> {
const payload: RPCState = {
event: eventName,
uuid: generateUUID(),
calledFrom: 'server',
calledTo: 'webview',
error: null,
data: args.length ? args : null,
player: player,
type: 'event',
}
const payload = this.request(eventName, 'webview', args, player)
emitNet(RPCEvents.LISTENER_SERVER, player, stringify(payload))
@@ -262,25 +206,13 @@ export class RPCInstanceServer extends Wrapper {
...args: CallbackArguments
) => Awaited<CallbackReturn> | Promise<Awaited<CallbackReturn>>,
): this {
if (this.debug) {
this.console.log(`[RPC]:onSelf ${eventName}`)
}
this._emitterLocal.on(eventName, cb)
return this
return this.listen(this._emitterLocal, 'onSelf', eventName, cb)
}
public offSelf<EventName extends keyof s.RPCEvents_Server>(
eventName: EventName,
): this {
if (this.debug) {
this.console.log(`[RPC]:offSelf ${eventName}`)
}
this._emitterLocal.off(eventName)
return this
return this.unlisten(this._emitterLocal, 'offSelf', eventName)
}
public async emitSelf<
@@ -288,29 +220,7 @@ export class RPCInstanceServer extends Wrapper {
Arguments extends Parameters<s.RPCEvents_Server[EventName]>,
Response extends ReturnType<s.RPCEvents_Server[EventName]>,
>(eventName: EventName, ...args: Arguments): Promise<Awaited<Response>> {
const payload: RPCState = {
event: eventName,
uuid: generateUUID(),
calledFrom: 'server',
calledTo: 'server',
error: null,
data: args.length ? args : null,
player: null,
type: 'event',
}
if (this.debug) {
this.console.log(
`[RPC]:accepted ${payload.event} from ${payload.calledFrom}`,
)
}
this.assertListener(this._emitterLocal, payload.event)
return await this._emitterLocal.emit<Awaited<Response>>(
payload.event,
...(payload.data && payload.data.length > 0 ? payload.data : []),
)
return this.emitLocal<Awaited<Response>>(eventName, args)
}
// ===== OTHER =====
@@ -323,9 +233,7 @@ export class RPCInstanceServer extends Wrapper {
cb: (player: number, args: CallbackArguments, commandRaw: string) => void,
restricted = false,
): this {
if (this.debug) {
this.console.log(`[RPC]:onCommand ${command}`)
}
this.log(`onCommand ${command}`)
RegisterCommand(command, cb, restricted)
@@ -340,9 +248,7 @@ export class RPCInstanceServer extends Wrapper {
throw new RPCError(RPCErrors.UNKNOWN_NATIVE, RPCErrors.UNKNOWN_NATIVE)
}
if (this.debug) {
this.console.log(`[RPC]:onNativeEvent ${eventName}`)
}
this.log(`onNativeEvent ${eventName}`)
on(eventName, cb)
+19 -99
View File
@@ -1,7 +1,7 @@
import type * as s from '@entityseven/fivem-rpc-shared-types'
import { Emitter } from '../utils/emitter'
import { generateUUID, stringify } from '../utils/funcs'
import { stringify } from '../utils/funcs'
import {
RPCEvents,
type RPCConfig,
@@ -9,9 +9,9 @@ import {
type RPCStateRaw,
type RPCStateWeb,
} from '../utils/types'
import { Wrapper } from './wrapper'
import { RPCInstanceBase } from './base'
export class RPCInstanceWebview extends Wrapper {
export class RPCInstanceWebview extends RPCInstanceBase {
private readonly _emitterClient: Emitter
private readonly _emitterServer: Emitter
@@ -21,7 +21,7 @@ export class RPCInstanceWebview extends Wrapper {
this._emitterClient = new Emitter()
this._emitterServer = new Emitter()
this.console.log('[RPC] Initialized Webview')
console.log('[RPC] Initialized Webview')
window.addEventListener('message', (e: MessageEvent<RPCStateWeb>) => {
if (e.data.origin === RPCEvents.LISTENER_CLIENT) {
@@ -36,11 +36,9 @@ export class RPCInstanceWebview extends Wrapper {
// ===== HANDLERS =====
private async _handleClient(payload: RPCState) {
if (this.debug) {
this.console.log(
`[RPC]:webview:accepted ${payload.type} ${payload.event} from ${payload.calledFrom}`,
)
}
this.log(
`accepted ${payload.type} ${payload.event} from ${payload.calledFrom}`,
)
if (payload.calledFrom === 'client' && payload.type === 'event') {
const response = await this.dispatch(this._emitterClient, payload)
@@ -50,11 +48,9 @@ export class RPCInstanceWebview extends Wrapper {
}
private async _handleServer(payload: RPCState) {
if (this.debug) {
this.console.log(
`[RPC]:webview:accepted ${payload.type} ${payload.event} from ${payload.calledFrom}`,
)
}
this.log(
`accepted ${payload.type} ${payload.event} from ${payload.calledFrom}`,
)
if (payload.calledFrom === 'server' && payload.type === 'event') {
const response = await this.dispatch(this._emitterServer, payload)
@@ -75,25 +71,13 @@ export class RPCInstanceWebview extends Wrapper {
...args: CallbackArguments
) => Awaited<CallbackReturn> | Promise<Awaited<CallbackReturn>>,
): this {
if (this.debug) {
this.console.log(`[RPC]:onClient ${eventName}`)
}
this._emitterClient.on(eventName, cb)
return this
return this.listen(this._emitterClient, 'onClient', eventName, cb)
}
public offClient<EventName extends keyof s.RPCEvents_ClientWebview>(
eventName: EventName,
): this {
if (this.debug) {
this.console.log(`[RPC]:offClient ${eventName}`)
}
this._emitterClient.off(eventName)
return this
return this.unlisten(this._emitterClient, 'offClient', eventName)
}
public async emitClient<
@@ -101,16 +85,7 @@ export class RPCInstanceWebview extends Wrapper {
Arguments extends Parameters<s.RPCEvents_WebviewClient[EventName]>,
Response extends ReturnType<s.RPCEvents_WebviewClient[EventName]>,
>(eventName: EventName, ...args: Arguments): Promise<Awaited<Response>> {
const payload: RPCState = {
event: eventName,
uuid: generateUUID(),
calledFrom: 'webview',
calledTo: 'client',
error: null,
data: args.length ? args : null,
player: null,
type: 'event',
}
const payload = this.request(eventName, 'client', args, null)
return this._request<Awaited<Response>>(payload)
}
@@ -127,25 +102,13 @@ export class RPCInstanceWebview extends Wrapper {
...args: CallbackArguments
) => Awaited<CallbackReturn> | Promise<Awaited<CallbackReturn>>,
): this {
if (this.debug) {
this.console.log(`[RPC]:onServer ${eventName}`)
}
this._emitterServer.on(eventName, cb)
return this
return this.listen(this._emitterServer, 'onServer', eventName, cb)
}
public offServer<EventName extends keyof s.RPCEvents_ServerWebview>(
eventName: EventName,
): RPCInstanceWebview {
if (this.debug) {
this.console.log(`[RPC]:offServer ${eventName}`)
}
this._emitterServer.off(eventName)
return this
return this.unlisten(this._emitterServer, 'offServer', eventName)
}
public async emitServer<
@@ -153,16 +116,7 @@ export class RPCInstanceWebview extends Wrapper {
Arguments extends Parameters<s.RPCEvents_WebviewServer[EventName]>,
Response extends ReturnType<s.RPCEvents_WebviewServer[EventName]>,
>(eventName: EventName, ...args: Arguments): Promise<Awaited<Response>> {
const payload: RPCState = {
event: eventName,
uuid: generateUUID(),
calledFrom: 'webview',
calledTo: 'server',
error: null,
data: args.length ? args : null,
player: null,
type: 'event',
}
const payload = this.request(eventName, 'server', args, null)
return this._request<Awaited<Response>>(payload)
}
@@ -179,25 +133,13 @@ export class RPCInstanceWebview extends Wrapper {
...args: CallbackArguments
) => Awaited<CallbackReturn> | Promise<Awaited<CallbackReturn>>,
): this {
if (this.debug) {
this.console.log(`[RPC]:onSelf ${eventName}`)
}
this._emitterLocal.on(eventName, cb)
return this
return this.listen(this._emitterLocal, 'onSelf', eventName, cb)
}
public offSelf<EventName extends keyof s.RPCEvents_Webview>(
eventName: EventName,
): this {
if (this.debug) {
this.console.log(`[RPC]:offSelf ${eventName}`)
}
this._emitterLocal.off(eventName)
return this
return this.unlisten(this._emitterLocal, 'offSelf', eventName)
}
public async emitSelf<
@@ -205,29 +147,7 @@ export class RPCInstanceWebview extends Wrapper {
Arguments extends Parameters<s.RPCEvents_Webview[EventName]>,
Response extends ReturnType<s.RPCEvents_Webview[EventName]>,
>(eventName: EventName, ...args: Arguments): Promise<Awaited<Response>> {
const payload: RPCState = {
event: eventName,
uuid: generateUUID(),
calledFrom: 'webview',
calledTo: 'webview',
error: null,
data: args.length ? args : null,
player: null,
type: 'event',
}
if (this.debug) {
this.console.log(
`[RPC]:accepted ${payload.event} from ${payload.calledFrom}`,
)
}
this.assertListener(this._emitterLocal, payload.event)
return await this._emitterLocal.emit<Awaited<Response>>(
payload.event,
...(payload.data && payload.data.length > 0 ? payload.data : []),
)
return this.emitLocal<Awaited<Response>>(eventName, args)
}
// ===== UTILS =====
+2 -5
View File
@@ -1,7 +1,6 @@
import { RPCInstanceClient } from './core/client'
import { RPCInstanceServer } from './core/server'
import { RPCInstanceWebview } from './core/webview'
import { Wrapper } from './core/wrapper'
import { RPCError } from './utils/errors'
import {
type RPCConfig,
@@ -27,7 +26,7 @@ import {
*
* @class
*/
class RPCFactory<T extends RPCEnvironment> extends Wrapper {
class RPCFactory<T extends RPCEnvironment> {
private readonly operator:
| RPCInstanceServer
| RPCInstanceClient
@@ -40,9 +39,7 @@ class RPCFactory<T extends RPCEnvironment> extends Wrapper {
* @param {boolean} opts.debug - Show additional logs
*/
constructor(opts: RPCConfig<T>) {
super(opts)
this.console.log('[RPC] Initializing...')
console.log('[RPC] Initializing...')
switch (opts.env) {
case 'server':
+1 -1
View File
@@ -4,7 +4,7 @@ import { RPCErrors } from './types'
* Accepts any callback. Argument types are enforced by the typed `on*`/`emit*`
* methods that wrap the emitter, not here.
*/
type Handler = (...args: never[]) => unknown
export type Handler = (...args: never[]) => unknown
/** One handler per event: registering an event again replaces its handler. */
export class Emitter {