//TODO: separate currently running status from enabled on reload //ugh am i gonna remake the internal plugin format again? (yes) /*[plugin name]: { enabled: Bool, //doubles as our running status (my explanation is too complex to fit in this comment so get fucked) iife: String, //we can't store functions in iDB? well fuck you, I'll make plugin devs package to an iife string desc: String //self-descriptory //TODO: should we be saving this in a separate metadata object? }*/ import { idb, nests } from "./common"; import logger from "./utils/logger"; const ctxNest: Nest = nests.make(); //Plugin context nest (I would create this in index, but it's not a good idea to expose that) let pluginNest: Nest<{ plugins: any }>; const pluginEval = (iife: string) => (0, eval)(iife); //defined as a separate function in case we want to do more things on plugin eval later async function savePlugin( eve: string, { path, value }: { path: string[] | string; value: any } ) { logger.debug( ["Plugins"], `Got ${eve} event for plugin manager's nest with path ${path} and val ${value}` ); await idb.set("demon", { plugins: pluginNest.ghost.plugins }); } async function init() { pluginNest = demon.summon("internal/nest"); //we don't have access to the global yet outside of the function if (!(await idb.get("demon"))) { await idb.set("demon", { plugins: {} //we need to pre-create this i guess? }); } pluginNest.store.plugins = (await idb.get("demon")).plugins; //we do this before we setup our hook to avoid any potential conflicts pluginNest.on(nests.Events.SET, savePlugin); pluginNest.on(nests.Events.DELETE, savePlugin); Object.keys(pluginNest.ghost.plugins).forEach((ele) => { if (pluginNest.ghost.plugins[ele].enabled) { const exports = pluginEval(pluginNest.ghost.plugins[ele].iife); const ctx = exports.onStart(); //actually starts plugin ctxNest.store[ele] = ctx; pluginNest.store.plugins[ele].enabled = true; //for clarity } else { pluginNest.store.plugins[ele].enabled = false; //for clarity } }); } function add(iife: string) { const exports = pluginEval(iife); logger.debug(["Plugins"], `Adding ${exports.meta.name}`); pluginNest.store.plugins[exports.meta.name] = { iife, enabled: false, desc: exports.meta.desc }; } function del(name: string) { if (!!pluginNest.ghost.plugins[name]) { logger.debug(["Plugins"], `Removing ${name}`); delete pluginNest.store.plugins[name]; } else { throw new Error("Can't delete plugin that doesn't exist. lol"); } } function toggle(name: string) { if (!!pluginNest.ghost.plugins[name]) { if (pluginNest.ghost.plugins[name].enabled) { logger.debug(["Plugins"], `Disabling ${name}`); const exports = pluginEval(pluginNest.ghost.plugins[name].iife); exports.onStop(ctxNest.store[name]); pluginNest.store.plugins[name].enabled = false; } else { logger.debug(["Plugins"], `Enabling ${name}`); const exports = pluginEval(pluginNest.ghost.plugins[name].iife); const ctx = exports.onStart(); ctxNest.store[name] = ctx; pluginNest.store.plugins[name].enabled = true; } } } export { init, add, del, toggle }; export default { init, add, del, toggle };