*Heavily refactor plugin api, remove most methods for now

*Introduce event emitter2 which will be used as part of api
*Use a proxy class to create a custom PluginAPI.registerMethod which will pass the lexical scoped plugin name
This commit is contained in:
Derrick Hammer 2022-12-18 11:09:29 -05:00
parent 523fe07028
commit 2b5d3ef646
Signed by: pcfreak30
GPG Key ID: C997C339BE476FF2
3 changed files with 103 additions and 61 deletions

View File

@ -38,6 +38,7 @@
"date-fns": "^2.28.0",
"dotenv": "^16.0.1",
"ethers": "^5.6.9",
"eventemitter2": "^6.4.9",
"express": "^4.18.1",
"fetch-blob": "https://github.com/LumeWeb/fetch-blob.git",
"hyperswarm": "^3.0.4",

View File

@ -1,36 +1,87 @@
import config from "../config.js";
import type { RPCServer } from "./rpc/server.js";
import { getRpcServer } from "./rpc/server.js";
import type { PluginAPI, RPCMethod, Plugin } from "@lumeweb/relay-types";
import type { Plugin, RPCMethod } from "@lumeweb/relay-types";
import slugify from "slugify";
import * as fs from "fs";
import path from "path";
import {
getSavedSsl,
getSsl,
getSslContext,
saveSSl,
setSsl,
setSSlCheck,
setSslContext,
} from "./ssl.js";
import log from "loglevel";
import type { Logger } from "loglevel";
import { getSeed } from "../lib/util.js";
import { getRouter, resetRouter, setRouter } from "./app.js";
import {
createIndependentFileSmall,
openIndependentFileSmall,
overwriteIndependentFileSmall,
} from "../lib/file";
import { setDnsProvider } from "./dns";
import pluginRpc from "./plugins/rpc";
import pluginCore from "./plugins/core";
import type Config from "@lumeweb/cfg";
import EventEmitter2 from "eventemitter2";
import log from "loglevel";
let pluginApi: PluginApiManager;
let pluginAPIManager: PluginAPIManager;
let pluginAPI: PluginAPI;
const sanitizeName = (name: string) =>
slugify(name, { lower: true, strict: true });
export class PluginApiManager {
class PluginAPI extends EventEmitter2 {
private _server: RPCServer;
constructor({
config,
logger,
server,
}: {
config: Config;
logger: Logger;
server: RPCServer;
}) {
super({
wildcard: true,
verboseMemoryLeak: true,
maxListeners: 0,
});
this._config = config;
this._logger = logger;
this._server = server;
}
private _config: Config;
get config(): Config {
return this._config;
}
private _logger: Logger;
get logger(): Logger {
return this._logger;
}
get rpcServer(): RPCServer {
return this._server;
}
public loadPlugin(
moduleName: string
): (moduleName: string) => Promise<Plugin> {
return getPluginAPIManager().loadPlugin;
}
get seed(): Uint8Array {
return getSeed();
}
registerMethod(methodName: string, method: RPCMethod): void {
throw new Error("not implemented and should not be called");
}
}
export function getPluginAPI(): PluginAPI {
if (!pluginAPI) {
pluginAPI = new PluginAPI({ config, logger: log, server: getRpcServer() });
}
return pluginAPI as PluginAPI;
}
export class PluginAPIManager {
private registeredPlugins: Map<string, Plugin> = new Map<string, Plugin>();
public async loadPlugin(moduleName: string): Promise<Plugin> {
@ -73,60 +124,42 @@ export class PluginApiManager {
this.registeredPlugins.set(plugin.name, plugin);
try {
plugin.plugin(this.getPluginAPI(plugin.name));
plugin.plugin(
// @ts-ignore
new Proxy<PluginAPI>(getPluginAPI(), {
get(target: PluginAPI, prop: string): any {
if (prop === "registerMethod") {
return (methodName: string, method: RPCMethod): void => {
return getRpcServer().registerMethod(
plugin.name,
methodName,
method
);
};
}
return (target as any)[prop];
},
})
);
} catch (e) {
throw e;
}
return plugin;
}
private getPluginAPI(pluginName: string): PluginAPI {
return {
config,
registerMethod: (methodName: string, method: RPCMethod): void => {
getRpcServer().registerMethod(pluginName, methodName, method);
},
loadPlugin: getPluginAPI().loadPlugin.bind(getPluginAPI()),
getRpcServer,
ssl: {
setContext: setSslContext,
getContext: getSslContext,
getSaved: getSavedSsl,
set: setSsl,
get: getSsl,
save: saveSSl,
setCheck: setSSlCheck,
},
files: {
createIndependentFileSmall,
openIndependentFileSmall,
overwriteIndependentFileSmall,
},
dns: {
setProvider: setDnsProvider,
},
logger: log,
getSeed,
appRouter: {
get: getRouter,
set: setRouter,
reset: resetRouter,
},
};
}
}
export function getPluginAPI(): PluginApiManager {
if (!pluginApi) {
pluginApi = new PluginApiManager();
export function getPluginAPIManager(): PluginAPIManager {
if (!pluginAPIManager) {
pluginAPIManager = new PluginAPIManager();
}
return pluginApi as PluginApiManager;
return pluginAPIManager as PluginAPIManager;
}
export async function loadPlugins() {
const api = await getPluginAPI();
const api = getPluginAPIManager();
api.loadPluginInstance(pluginCore);
api.loadPluginInstance(pluginRpc);

View File

@ -674,6 +674,7 @@ __metadata:
date-fns: "npm:^2.28.0"
dotenv: "npm:^16.0.1"
ethers: "npm:^5.6.9"
eventemitter2: "npm:^6.4.9"
express: "npm:^4.18.1"
fetch-blob: "https://github.com/LumeWeb/fetch-blob.git"
hyper-typings: "npm:^1.0.0"
@ -2115,6 +2116,13 @@ __metadata:
languageName: node
linkType: hard
"eventemitter2@npm:^6.4.9":
version: 6.4.9
resolution: "eventemitter2@npm:6.4.9"
checksum: c180cc0012389f2cd564cdfba949807175dd309b1d7f0900cfdfc5a97436a867a30964b94f86613ab237d960d52f7e4c85098c9c8ef6dc8ed29bbf4e79465d8b
languageName: node
linkType: hard
"eventemitter3@npm:^4.0.7":
version: 4.0.7
resolution: "eventemitter3@npm:4.0.7"