*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", "date-fns": "^2.28.0",
"dotenv": "^16.0.1", "dotenv": "^16.0.1",
"ethers": "^5.6.9", "ethers": "^5.6.9",
"eventemitter2": "^6.4.9",
"express": "^4.18.1", "express": "^4.18.1",
"fetch-blob": "https://github.com/LumeWeb/fetch-blob.git", "fetch-blob": "https://github.com/LumeWeb/fetch-blob.git",
"hyperswarm": "^3.0.4", "hyperswarm": "^3.0.4",

View File

@ -1,36 +1,87 @@
import config from "../config.js"; import config from "../config.js";
import type { RPCServer } from "./rpc/server.js";
import { getRpcServer } 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 slugify from "slugify";
import * as fs from "fs"; import * as fs from "fs";
import path from "path"; import path from "path";
import { import type { Logger } from "loglevel";
getSavedSsl,
getSsl,
getSslContext,
saveSSl,
setSsl,
setSSlCheck,
setSslContext,
} from "./ssl.js";
import log from "loglevel";
import { getSeed } from "../lib/util.js"; 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 pluginRpc from "./plugins/rpc";
import pluginCore from "./plugins/core"; 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) => const sanitizeName = (name: string) =>
slugify(name, { lower: true, strict: true }); 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>(); private registeredPlugins: Map<string, Plugin> = new Map<string, Plugin>();
public async loadPlugin(moduleName: string): Promise<Plugin> { public async loadPlugin(moduleName: string): Promise<Plugin> {
@ -73,60 +124,42 @@ export class PluginApiManager {
this.registeredPlugins.set(plugin.name, plugin); this.registeredPlugins.set(plugin.name, plugin);
try { 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) { } catch (e) {
throw e; throw e;
} }
return plugin; 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 { export function getPluginAPIManager(): PluginAPIManager {
if (!pluginApi) { if (!pluginAPIManager) {
pluginApi = new PluginApiManager(); pluginAPIManager = new PluginAPIManager();
} }
return pluginApi as PluginApiManager; return pluginAPIManager as PluginAPIManager;
} }
export async function loadPlugins() { export async function loadPlugins() {
const api = await getPluginAPI(); const api = getPluginAPIManager();
api.loadPluginInstance(pluginCore); api.loadPluginInstance(pluginCore);
api.loadPluginInstance(pluginRpc); api.loadPluginInstance(pluginRpc);

View File

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