summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlam3rboy <34555296+Flam3rboy@users.noreply.github.com>2022-08-13 02:42:08 +0200
committerTheArcaneBrony <myrainbowdash949@gmail.com>2022-09-04 10:48:54 +0200
commit2c40b1ebae53ebd8af4a375d8d3eb2bdb425c2dd (patch)
tree4a2d42982c02dc77949ffbcb98e4d3e96d42f017
parentfeat(plugins): loader (diff)
downloadserver-2c40b1ebae53ebd8af4a375d8d3eb2bdb425c2dd.tar.xz
feat(plugins): event system
-rw-r--r--src/util/plugin/Plugin.ts18
-rw-r--r--src/util/plugin/PluginLoader.ts53
-rw-r--r--src/util/util/imports/TypedEmitter.ts41
-rw-r--r--src/util/util/imports/index.ts1
4 files changed, 85 insertions, 28 deletions
diff --git a/src/util/plugin/Plugin.ts b/src/util/plugin/Plugin.ts
index 246e9931..96e05843 100644
--- a/src/util/plugin/Plugin.ts
+++ b/src/util/plugin/Plugin.ts
@@ -1,5 +1,13 @@
-export class Plugin {
-    onPluginLoaded() {
-        console.log('no onpluginloaded!')
-    }
-}
\ No newline at end of file
+import EventEmitter from "events";
+import { TypedEventEmitter } from "@fosscord/util";
+
+type PluginEvents = {
+	error: (error: Error | unknown) => void;
+	loaded: () => void;
+};
+
+export class Plugin extends (EventEmitter as new () => TypedEventEmitter<PluginEvents>) {
+	async init() {
+		// insert default config into database?
+	}
+}
diff --git a/src/util/plugin/PluginLoader.ts b/src/util/plugin/PluginLoader.ts
index eadfb912..b46ef269 100644
--- a/src/util/plugin/PluginLoader.ts
+++ b/src/util/plugin/PluginLoader.ts
@@ -6,27 +6,34 @@ const root = process.env.PLUGIN_LOCATION || "../plugins";
 
 let pluginsLoaded = false;
 export class PluginLoader {
-    public static loadPlugins() {
+	public static loadPlugins() {
+		console.log(`Plugin root directory: ${path.resolve(root)}`);
+		const dirs = fs.readdirSync(root).filter((x) => {
+			try {
+				fs.readdirSync(path.join(root, x));
+				return true;
+			} catch (e) {
+				return false;
+			}
+		});
+		console.log(dirs);
+		dirs.forEach(async (x) => {
+			let modPath = path.resolve(path.join(root, x));
+			console.log(`Trying to load plugin: ${modPath}`);
+			const manifest = require(path.join(modPath, "plugin.json")) as PluginManifest;
+			console.log(
+				`Plugin info: ${manifest.name} (${manifest.id}), written by ${manifest.authors}, available at ${manifest.repository}`
+			);
+			const module_ = require(path.join(modPath, "dist", "index.js")) as Plugin;
+			try {
+				await module_.init();
+				module_.emit("loaded");
+			} catch (error) {
+				module_.emit("error", error);
+			}
+		});
 
-        console.log(`Plugin root directory: ${path.resolve(root)}`);
-        const dirs = fs.readdirSync(root).filter(x => {
-            try {
-                fs.readdirSync(path.join(root, x));
-                return true; 
-            } catch (e) { 
-                return false; 
-            }
-        });
-        console.log(dirs)
-        dirs.forEach(x=>{
-            let modPath = path.resolve(path.join(root, x));
-            console.log(`Trying to load plugin: ${modPath}`)
-            const manifest = require(path.join(modPath, "plugin.json")) as PluginManifest;
-            console.log(`Plugin info: ${manifest.name} (${manifest.id}), written by ${manifest.authors}, available at ${manifest.repository}`)
-            const module_ = require(path.join(modPath, "dist", "index.js")) as Plugin;
-            module_.onPluginLoaded();
-        })
-        //
-        //module_.pluginPath = 
-    }
-}
\ No newline at end of file
+		//
+		//module_.pluginPath =
+	}
+}
diff --git a/src/util/util/imports/TypedEmitter.ts b/src/util/util/imports/TypedEmitter.ts
new file mode 100644
index 00000000..7a0fffe2
--- /dev/null
+++ b/src/util/util/imports/TypedEmitter.ts
@@ -0,0 +1,41 @@
+export type EventMap = {
+	[key: string]: (...args: any[]) => void;
+};
+
+/**
+ * Type-safe event emitter.
+ *
+ * Use it like this:
+ *
+ * ```typescript
+ * type MyEvents = {
+ *   error: (error: Error) => void;
+ *   message: (from: string, content: string) => void;
+ * }
+ *
+ * const myEmitter = new EventEmitter() as TypedEmitter<MyEvents>;
+ *
+ * myEmitter.emit("error", "x")  // <- Will catch this type error;
+ * ```
+ */
+export interface TypedEventEmitter<Events extends EventMap> {
+	addListener<E extends keyof Events>(event: E, listener: Events[E]): this;
+	on<E extends keyof Events>(event: E, listener: Events[E]): this;
+	once<E extends keyof Events>(event: E, listener: Events[E]): this;
+	prependListener<E extends keyof Events>(event: E, listener: Events[E]): this;
+	prependOnceListener<E extends keyof Events>(event: E, listener: Events[E]): this;
+
+	off<E extends keyof Events>(event: E, listener: Events[E]): this;
+	removeAllListeners<E extends keyof Events>(event?: E): this;
+	removeListener<E extends keyof Events>(event: E, listener: Events[E]): this;
+
+	emit<E extends keyof Events>(event: E, ...args: Parameters<Events[E]>): boolean;
+	// The sloppy `eventNames()` return type is to mitigate type incompatibilities - see #5
+	eventNames(): (keyof Events | string | symbol)[];
+	rawListeners<E extends keyof Events>(event: E): Events[E][];
+	listeners<E extends keyof Events>(event: E): Events[E][];
+	listenerCount<E extends keyof Events>(event: E): number;
+
+	getMaxListeners(): number;
+	setMaxListeners(maxListeners: number): this;
+}
diff --git a/src/util/util/imports/index.ts b/src/util/util/imports/index.ts
index 120cff11..844aee4f 100644
--- a/src/util/util/imports/index.ts
+++ b/src/util/util/imports/index.ts
@@ -1,3 +1,4 @@
 export * from "./Checks";
 export * from "./HTTPError";
 export * from "./OrmUtils";
+export * from "./TypedEmitter";