flashlang/src/communicator.ts

66 lines
1.6 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-explicit-any */
import type { Runtime } from "webextension-polyfill";
export interface commandFunction {
args: any;
return: any;
}
export interface commandList {
[functionName: string]: commandFunction;
}
interface commandMessage<T extends commandList, K extends keyof T> {
name: K;
args: T[K]["args"];
}
declare type listener<T extends commandList, K extends keyof T> = (
args: T[K]["args"],
s?: Runtime.MessageSender
) => Promise<T[K]["return"]> | T[K]["return"];
export abstract class Communicator<
RecvCommands extends commandList,
SendCommands extends commandList
> {
private listeners = new Map<
keyof RecvCommands,
listener<RecvCommands, keyof RecvCommands>
>();
abstract runCommand<K extends keyof SendCommands>(
command: K,
args: SendCommands[K]["args"],
...rest: unknown[]
): Promise<SendCommands[K]["return"]>;
addMessageListener<K extends keyof RecvCommands>(
command: K,
callback: listener<RecvCommands, K>
) {
this.listeners.set(command, callback as any);
}
protected getCommandMessage<K extends keyof RecvCommands>(
command: K,
...args: RecvCommands[K]["args"]
): commandMessage<RecvCommands, K> {
return { name: command, args: args };
}
protected onMessage<K extends keyof RecvCommands>(
m: commandMessage<RecvCommands, K>,
s?: Runtime.MessageSender
) {
const listener = this.listeners.get(m.name);
const args: [
RecvCommands[keyof RecvCommands]["args"],
Runtime.MessageSender
] = m.args;
if (args[0] === undefined) args.pop();
args.push(s);
if (listener) return listener(...args);
}
}