diff --git a/.vscode/settings.json b/.vscode/settings.json index b080f0d..c58fe3a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,4 +7,4 @@ "[json]": { "editor.defaultFormatter": "denoland.vscode-deno" } -} \ No newline at end of file +} diff --git a/examples/abort-controller.ts b/examples/abort-controller.ts index 338a7c4..3e4cdf2 100644 --- a/examples/abort-controller.ts +++ b/examples/abort-controller.ts @@ -12,6 +12,7 @@ const receiver = new LogReceiver({ console.log("Log receiver running.. "); receiver.on("event", (message) => console.log(message)); -receiver.on("close", () => console.log("Closed the socket")); controller.abort(); + +console.log("Closed the socket") diff --git a/src/logReceiver.ts b/src/logReceiver.ts index 24705f2..f040371 100644 --- a/src/logReceiver.ts +++ b/src/logReceiver.ts @@ -2,7 +2,7 @@ import { EventEmitter } from "node:events"; import { createSocket, type RemoteInfo, type Socket } from "node:dgram"; import { parsePacket } from "./parser.ts"; -import type { EventData } from "./types.ts"; +import type { EventData, TypedEventEmitter } from "./types.ts"; /** * The socket options for the UDP socket @@ -30,6 +30,11 @@ export interface LogReceiverOptions { signal?: AbortSignal; } +type MessageEvents = { + error: (error: Error) => void; + event: (message: EventData) => void; +}; + /** * An event emitter that will emit a message event when a valid UDP log is created on the server * @@ -94,7 +99,7 @@ export interface LogReceiverOptions { * * For security reasons, you should always use a log secret to prevent evaluation of potentially malicious messages. Do this by looking at the password field. In order to set up the log secret, you can use the `sv_logsecret` command */ -export class LogReceiver extends EventEmitter implements Disposable { +export class LogReceiver extends (EventEmitter as new () => TypedEventEmitter) implements Disposable { #socket: Socket; /** @@ -118,10 +123,7 @@ export class LogReceiver extends EventEmitter implements Disposable { this.#socket.bind(port, address); - this.#socket.on("close", () => this.emit("close")); - this.#socket.on("connect", () => this.emit("connect")); this.#socket.on("error", (error) => this.emit("error", error)); - this.#socket.on("listening", () => this.emit("listening")); this.#socket.on("message", (buffer, serverInfo) => this.#handleMessage(buffer, serverInfo)); } diff --git a/src/types.ts b/src/types.ts index 11aef8c..ae97b66 100644 --- a/src/types.ts +++ b/src/types.ts @@ -24,3 +24,47 @@ export interface EventData extends ParsedLogMessage { */ socket: RemoteInfo; } + +type EventMap = { + // deno-lint-ignore no-explicit-any + [key: string]: (...args: any[]) => void; +}; + +/** + * Copied from https://github.com/andywer/typed-emitter/blob/master/index.d.ts + * Type-safe event emitter + * + * Use it like this: + * + * ```ts + * type MyEvents = { + * error: (error: Error) => void; + * message: (from: string, content: string) => void; + * } + * + * const myEmitter = new EventEmitter() as TypedEmitter; + * + * myEmitter.emit("error", "x") // <- Will catch this type error; + * ``` + */ +export interface TypedEventEmitter { + addListener(event: E, listener: Events[E]): this; + on(event: E, listener: Events[E]): this; + once(event: E, listener: Events[E]): this; + prependListener(event: E, listener: Events[E]): this; + prependOnceListener(event: E, listener: Events[E]): this; + + off(event: E, listener: Events[E]): this; + removeAllListeners(event?: E): this; + removeListener(event: E, listener: Events[E]): this; + + emit(event: E, ...args: Parameters): boolean; + // The sloppy `eventNames()` return type is to mitigate type incompatibilities - see #5 + eventNames(): (keyof Events | string | symbol)[]; + rawListeners(event: E): Events[E][]; + listeners(event: E): Events[E][]; + listenerCount(event: E): number; + + getMaxListeners(): number; + setMaxListeners(maxListeners: number): this; +} diff --git a/tests/parser.bench.ts b/tests/parser.bench.ts index 4748e3b..29db165 100644 --- a/tests/parser.bench.ts +++ b/tests/parser.bench.ts @@ -22,4 +22,4 @@ Deno.bench("Can parse a password", { baseline: true, group: "password" }, () => assertEquals(result?.message, body.substring(2)); assertEquals(result?.password, password); -}); \ No newline at end of file +}); diff --git a/tests/parser.test.ts b/tests/parser.test.ts index 2096d85..f04c628 100644 --- a/tests/parser.test.ts +++ b/tests/parser.test.ts @@ -57,4 +57,4 @@ Deno.test("Can parse a password", () => { assertEquals(result?.message, body.substring(2)); assertEquals(result?.password, password); -}); \ No newline at end of file +});