import { EventEmitter } from "events"; type Awaitable = Promise | T; // Event Typing interface PollEvents { item: (item: T) => void; listing: (items: T[]) => void; end: () => void; } export default interface Poll { on>(event: U, listener: PollEvents[U]): this; once>( event: U, listener: PollEvents[U] ): this; off>( event: U, listener: PollEvents[U] ): this; } export interface PollConfiguration { frequency: number; get: () => Awaitable; identifier: keyof T; } export default class Poll extends EventEmitter { frequency: number; interval: NodeJS.Timeout; processed: Set = new Set(); constructor({ frequency, get, identifier }: PollConfiguration) { super(); this.frequency = frequency || 2000; this.interval = setInterval(async () => { const batch = await get(); const newItems: T[] = []; for (const item of batch) { const id = item[identifier]; if (this.processed.has(id)) continue; // Emit for new items and add it to the list newItems.push(item); this.processed.add(id); this.emit("item", item); } // Emit the new listing of all new items this.emit("listing", newItems); }, frequency); } end() { clearInterval(this.interval); this.emit("end"); } }