2023-01-31 10:02:20 +00:00
|
|
|
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";
|
2023-02-01 12:42:16 +00:00
|
|
|
import { EventEmitter2 as EventEmitter } from "eventemitter2";
|
2023-01-31 10:02:20 +00:00
|
|
|
|
|
|
|
type callModuleBound = (method: string, data?: any) => Promise<ErrTuple>;
|
|
|
|
type connectModuleBound = (
|
|
|
|
method: string,
|
|
|
|
data: any,
|
|
|
|
receiveUpdate: DataFn
|
|
|
|
) => [sendUpdate: DataFn, response: Promise<ErrTuple>];
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2023-02-01 12:42:16 +00:00
|
|
|
export abstract class Client extends EventEmitter {
|
2023-01-31 10:02:20 +00:00
|
|
|
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<void> {
|
|
|
|
if (this._callModule && this._connectModule) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const moduleBag = await this.loadBound(module);
|
|
|
|
this._callModule = async (...args) => {
|
|
|
|
const ret = await moduleBag.callModule(...args);
|
2023-02-01 12:26:56 +00:00
|
|
|
return this.handleErrorOrReturn(ret);
|
2023-01-31 10:02:20 +00:00
|
|
|
};
|
|
|
|
this._connectModule = moduleBag.connectModule;
|
|
|
|
}
|
|
|
|
|
|
|
|
public async loadBound(module: string): Promise<ModuleBagBound> {
|
|
|
|
return (await load(module)) as ModuleBagBound;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected handleError(ret: ErrTuple): void {
|
|
|
|
if (ret[1]) {
|
|
|
|
throw new Error(ret[1]);
|
|
|
|
}
|
|
|
|
}
|
2023-02-01 12:26:56 +00:00
|
|
|
protected handleErrorOrReturn(ret: ErrTuple): any {
|
|
|
|
this.handleError(ret);
|
|
|
|
return ret[0];
|
|
|
|
}
|
2023-01-31 10:02:20 +00:00
|
|
|
protected async callModuleReturn(method: string, data?: any): Promise<any> {
|
|
|
|
const ret = await this.callModule(method, data);
|
|
|
|
|
|
|
|
return ret[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function load(
|
|
|
|
module?: string
|
|
|
|
): Promise<ModuleBag | ModuleBagBound> {
|
2023-01-31 12:42:36 +00:00
|
|
|
if (callModule && connectModule) {
|
2023-01-31 10:02:20 +00:00
|
|
|
if (module) {
|
|
|
|
return {
|
|
|
|
callModule: callModule.bind(undefined, module),
|
|
|
|
connectModule: connectModule.bind(undefined, module),
|
|
|
|
log,
|
|
|
|
logErr,
|
|
|
|
} as ModuleBagBound;
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
callModule,
|
|
|
|
connectModule,
|
|
|
|
log,
|
|
|
|
logErr,
|
|
|
|
} as ModuleBag;
|
|
|
|
}
|
|
|
|
|
2023-01-31 12:48:47 +00:00
|
|
|
const pkg =
|
2023-01-31 10:02:20 +00:00
|
|
|
typeof window !== "undefined" && window?.document
|
2023-01-31 12:48:47 +00:00
|
|
|
? await import("libkernel")
|
|
|
|
: await import("libkmodule");
|
2023-01-31 10:02:20 +00:00
|
|
|
|
|
|
|
callModule = pkg.callModule;
|
|
|
|
connectModule = pkg.connectModule;
|
2023-01-31 12:48:47 +00:00
|
|
|
// @ts-ignore
|
2023-01-31 10:02:20 +00:00
|
|
|
log = pkg.log;
|
2023-01-31 12:48:47 +00:00
|
|
|
// @ts-ignore
|
2023-01-31 10:02:20 +00:00
|
|
|
logErr = pkg.logErr;
|
|
|
|
|
|
|
|
return load(module);
|
|
|
|
}
|
|
|
|
|
|
|
|
type ClientConstructor<U> = new (...args: any[]) => U;
|
|
|
|
|
|
|
|
export const factory = function <T extends Client = Client>(
|
|
|
|
type: ClientConstructor<T>,
|
|
|
|
module: string
|
|
|
|
) {
|
|
|
|
return function (...args: any): T {
|
|
|
|
return new Proxy<T>(new type(...args), {
|
|
|
|
get(target: T, property: string) {
|
2023-01-31 13:04:48 +00:00
|
|
|
const prop = target[property as keyof T];
|
|
|
|
|
|
|
|
if (typeof prop !== "function") {
|
|
|
|
return prop;
|
|
|
|
}
|
|
|
|
|
|
|
|
return async (...args: any[]): Promise<any> => {
|
2023-01-31 10:02:20 +00:00
|
|
|
await target.loadLibs(module);
|
|
|
|
|
2023-01-31 13:04:48 +00:00
|
|
|
return (target[property as keyof T] as Function)(...args);
|
2023-01-31 10:02:20 +00:00
|
|
|
};
|
|
|
|
},
|
|
|
|
});
|
|
|
|
};
|
|
|
|
};
|