diff --git a/package.json b/package.json index b5746cb..f426943 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/modules/plugin.ts b/src/modules/plugin.ts index b67ad20..4434d8d 100644 --- a/src/modules/plugin.ts +++ b/src/modules/plugin.ts @@ -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 { + 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 = new Map(); public async loadPlugin(moduleName: string): Promise { @@ -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(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); diff --git a/yarn.lock b/yarn.lock index 0624662..651f3d3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"