relay/src/modules/plugin.ts

127 lines
3.1 KiB
TypeScript
Raw Normal View History

2022-09-21 12:59:22 +00:00
import config from "../config.js";
import { getRpcServer } from "../rpc/server.js";
2022-08-29 02:40:25 +00:00
import type { PluginAPI, RPCMethod, Plugin } from "@lumeweb/relay-types";
import slugify from "slugify";
2022-08-28 04:26:24 +00:00
import * as fs from "fs";
import path from "path";
import {
getSavedSsl,
getSsl,
getSslContext,
saveSSl,
setSsl,
setSSlCheck,
setSslContext,
} from "./ssl.js";
import log from "loglevel";
2022-09-21 12:59:22 +00:00
import { getSeed } from "../lib/util.js";
2022-09-21 12:56:24 +00:00
import { getRouter, resetRouter, setRouter } from "./app.js";
import {
createIndependentFileSmall,
openIndependentFileSmall,
overwriteIndependentFileSmall,
2022-09-21 12:59:22 +00:00
} from "../lib/file";
import { setDnsProvider } from "./dns";
let pluginApi: PluginApiManager;
const sanitizeName = (name: string) =>
slugify(name, { lower: true, strict: true });
export class PluginApiManager {
private registeredPlugins: Map<string, Plugin> = new Map<string, Plugin>();
public async loadPlugin(moduleName: string): Promise<Plugin> {
moduleName = sanitizeName(moduleName);
if (this.registeredPlugins.has(moduleName)) {
return this.registeredPlugins.get(moduleName) as Plugin;
}
2022-08-28 04:26:24 +00:00
const paths = [];
for (const modulePath of [`${moduleName}.js`, `${moduleName}.mjs`]) {
2022-09-21 20:11:02 +00:00
const fullPath = path.join(config.get("plugindir"), modulePath);
2022-08-28 04:26:24 +00:00
if (fs.existsSync(fullPath)) {
paths.push(fullPath);
break;
}
}
if (!paths.length) {
throw new Error(`Plugin ${moduleName} does not exist`);
}
let plugin: Plugin;
try {
plugin = (await import(paths.shift() as string)) as Plugin;
} catch (e) {
throw e;
}
if ("default" in plugin) {
plugin = plugin?.default as Plugin;
}
plugin.name = sanitizeName(plugin.name);
this.registeredPlugins.set(plugin.name, plugin);
try {
plugin.plugin(this.getPluginAPI(plugin.name));
} catch (e) {
throw e;
}
return plugin;
}
private getPluginAPI(pluginName: string): PluginAPI {
return {
config,
registerMethod: (methodName: string, method: RPCMethod): void => {
getRpcServer().registerMethod(pluginName, methodName, method);
},
2022-08-29 02:39:51 +00:00
loadPlugin: getPluginAPI().loadPlugin.bind(getPluginAPI()),
getMethods: getRpcServer().getMethods.bind(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();
}
return pluginApi as PluginApiManager;
}
export async function loadPlugins() {
2022-09-21 20:03:12 +00:00
for (const plugin of [...new Set(config.array("plugins", []))] as []) {
await getPluginAPI().loadPlugin(plugin);
}
}