any> = (
...args: TFunction extends (...args: infer P) => any ? TransferTypes : never
) => ReturnType;
type Transferrable any }> = {
[Key in keyof Base]: MakeFunctionTransferrable;
};
export type Proxify = Promisify>>;
export function createDispatchProxyFromFn(
class_: { new (...args: any[]): T },
requestFn: (fn: string) => (...args: any[]) => Promise,
): Proxify {
const proxy: any = class_.prototype instanceof EventEmitter ? new EventEmitter() : {};
for (const fn of Object.getOwnPropertyNames(class_.prototype)) {
if (fn === 'constructor') {
continue;
}
proxy[fn] = requestFn(fn);
}
return proxy;
}
export function createDispatchProxy(
class_: { new (...args: any[]): T },
transportClient: TransportClient,
): Proxify {
// Create a proxy of class_ that passes along methods over our transportClient
const proxy = createDispatchProxyFromFn(class_, (fn: string) => (...args: any[]) => {
// Pass our proxied function name and arguments over our transport client
const transfer: Transferable[] = args.reduce(
(acc, a) => (isTransferDescriptor(a) ? [...acc, ...a.transferables] : acc),
[] as Transferable[],
);
args = args.map(a => (isTransferDescriptor(a) ? a.send : a));
return transportClient.request({ fn, args }, transfer);
});
if (proxy instanceof EventEmitter) {
// Handle proxied 'emit' calls if our proxy object is an EventEmitter
transportClient.on('event_msg', ({ fn, args }) => {
if (fn === 'emit') {
const [eventName, ...restArgs] = args;
proxy.emit(eventName, ...restArgs);
}
});
}
return proxy;
}