type callModule = typeof import("libkmodule").callModule; type connectModule = typeof import("libkmodule").connectModule; type logErr = typeof import("libkmodule").logErr; type log = typeof import("libkmodule").log; import type { ErrTuple, DataFn } from "@siaweb/libweb"; type callModuleBound = (method: string, data?: any) => Promise; type connectModuleBound = ( method: string, data: any, receiveUpdate: DataFn ) => [sendUpdate: DataFn, response: Promise]; let callModule: callModule; let connectModule: connectModule; let log: log; let logErr: logErr; export interface ModuleBag { callModule: callModule; connectModule: connectModule; log: log; logErr: logErr; } export interface ModuleBagBound extends ModuleBag { callModule: callModuleBound; connectModule: connectModuleBound; } export abstract class Client { private _callModule?: callModuleBound; get callModule(): callModuleBound { return this._callModule as callModuleBound; } private _connectModule?: connectModuleBound; get connectModule(): connectModuleBound { return this._connectModule as connectModuleBound; } public async loadLibs(module: string): Promise { if (this._callModule && this._connectModule) { return; } const moduleBag = await this.loadBound(module); this._callModule = async (...args) => { const ret = await moduleBag.callModule(...args); this.handleError(ret); return ret; }; this._connectModule = moduleBag.connectModule; } public async loadBound(module: string): Promise { return (await load(module)) as ModuleBagBound; } protected handleError(ret: ErrTuple): void { if (ret[1]) { throw new Error(ret[1]); } } protected async callModuleReturn(method: string, data?: any): Promise { const ret = await this.callModule(method, data); return ret[0]; } } export async function load( module?: string ): Promise { if (callModule !== null && connectModule !== null) { if (module) { return { callModule: callModule.bind(undefined, module), connectModule: connectModule.bind(undefined, module), log, logErr, } as ModuleBagBound; } return { callModule, connectModule, log, logErr, } as ModuleBag; } const pkgName = typeof window !== "undefined" && window?.document ? "libkernel" : "libkmodule"; const pkg = await import(pkgName); callModule = pkg.callModule; connectModule = pkg.connectModule; log = pkg.log; logErr = pkg.logErr; return load(module); } type ClientConstructor = new (...args: any[]) => U; export const factory = function ( type: ClientConstructor, module: string ) { return function (...args: any): T { return new Proxy(new type(...args), { get(target: T, property: string) { return async (): Promise => { await target.loadLibs(module); return target[property as keyof T]; }; }, }); }; };