UNPKG

@sapphire/event-iterator

Version:
1 lines 9.32 kB
{"version":3,"sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAA,MAAA,EAAA,KAAA,EAAA,MAAA,EAAA,OAAA,EAAA,MAAA,EAAA,UAAA,EAAA,KAAA;AA8BO,IAAM,cAAA,GAAN,MAAM,cAAuE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwD5E,WAAY,CAAA,OAAA,EAAuB,KAAe,EAAA,OAAA,GAAmC,EAAI,EAAA;AApDhG;AAAA;AAAA;AAAA,IAAgB,aAAA,CAAA,IAAA,EAAA,SAAA,CAAA;AAKhB;AAAA;AAAA;AAAA,IAAgB,aAAA,CAAA,IAAA,EAAA,OAAA,CAAA;AAKhB;AAAA;AAAA;AAAA,IAAO,aAAA,CAAA,IAAA,EAAA,QAAA,CAAA;AAKP;AAAA;AAAA;AAAA,IAAS,YAAA,CAAA,IAAA,EAAA,MAAA,EAAA,KAAA,CAAA;AAKT;AAAA;AAAA;AAAA,IAAS,YAAA,CAAA,IAAA,EAAA,KAAA,CAAA;AAKT;AAAA;AAAA;AAAA,IAAA,YAAA,CAAA,IAAA,EAAA,MAAA,EAAc,EAAC,CAAA;AAKf;AAAA;AAAA;AAAA,IAAU,YAAA,CAAA,IAAA,EAAA,OAAA,EAAA,CAAA,CAAA;AAKV;AAAA;AAAA;AAAA,IAAS,YAAA,CAAA,IAAA,EAAA,MAAA,CAAA;AAKT;AAAA;AAAA;AAAA,IAAA,YAAA,CAAA,IAAA,EAAS,UAAgD,EAAA,IAAA,CAAA;AAKzD;AAAA;AAAA;AAAA,IAAS,YAAA,CAAA,IAAA,EAAA,KAAA,CAAA;AAQR,IAAA,IAAA,CAAK,OAAU,GAAA,OAAA;AACf,IAAA,IAAA,CAAK,KAAQ,GAAA,KAAA;AACb,IAAK,YAAA,CAAA,IAAA,EAAA,MAAA,EAAS,QAAQ,KAAS,IAAA,QAAA,CAAA;AAC/B,IAAA,YAAA,CAAA,IAAA,EAAK,OAAQ,OAAQ,CAAA,IAAA,CAAA;AACrB,IAAK,IAAA,CAAA,MAAA,GAAS,OAAQ,CAAA,MAAA,KAAW,MAAe,IAAA,CAAA;AAGhD,IAAI,IAAA,YAAA,CAAA,IAAA,EAAK,KAAO,CAAA,EAAA,YAAA,CAAA,IAAA,EAAK,UAAa,EAAA,UAAA,CAAW,IAAK,CAAA,GAAA,CAAI,IAAK,CAAA,IAAI,CAAG,EAAA,YAAA,CAAA,IAAA,EAAK,KAAK,CAAA,CAAA,CAAA;AAE5E,IAAA,YAAA,CAAA,IAAA,EAAK,KAAQ,EAAA,IAAA,CAAK,IAAK,CAAA,IAAA,CAAK,IAAI,CAAA,CAAA;AAChC,IAAM,MAAA,YAAA,GAAe,IAAK,CAAA,OAAA,CAAQ,eAAgB,EAAA;AAClD,IAAA,IAAI,iBAAiB,CAAG,EAAA,IAAA,CAAK,OAAQ,CAAA,eAAA,CAAgB,eAAe,CAAC,CAAA;AAErE,IAAA,IAAA,CAAK,OAAQ,CAAA,EAAA,CAAG,IAAK,CAAA,KAAA,EAAO,mBAAK,KAAK,CAAA,CAAA;AAAA;AACvC;AAAA;AAAA;AAAA,EAKA,IAAW,KAAiB,GAAA;AAC3B,IAAA,OAAO,YAAK,CAAA,IAAA,EAAA,MAAA,CAAA;AAAA;AACb;AAAA;AAAA;AAAA,EAKO,GAAY,GAAA;AAClB,IAAA,IAAI,mBAAK,MAAQ,CAAA,EAAA;AACjB,IAAA,YAAA,CAAA,IAAA,EAAK,MAAS,EAAA,IAAA,CAAA;AACd,IAAA,YAAA,CAAA,IAAA,EAAK,QAAS,EAAC,CAAA;AAEf,IAAA,IAAA,CAAK,OAAQ,CAAA,GAAA,CAAI,IAAK,CAAA,KAAA,EAAO,mBAAK,KAAK,CAAA,CAAA;AACvC,IAAM,MAAA,YAAA,GAAe,IAAK,CAAA,OAAA,CAAQ,eAAgB,EAAA;AAClD,IAAA,IAAI,iBAAiB,CAAG,EAAA,IAAA,CAAK,OAAQ,CAAA,eAAA,CAAgB,eAAe,CAAC,CAAA;AAAA;AACtE;AAAA;AAAA;AAAA,EAKA,MAAa,IAAmC,GAAA;AAE/C,IAAI,IAAA,YAAA,CAAA,IAAA,EAAK,QAAO,MAAQ,EAAA;AACvB,MAAM,MAAA,KAAA,GAAQ,YAAK,CAAA,IAAA,EAAA,MAAA,CAAA,CAAO,KAAM,EAAA;AAChC,MAAA,IAAI,CAAC,IAAK,CAAA,MAAA,CAAO,KAAK,CAAG,EAAA,OAAO,KAAK,IAAK,EAAA;AAC1C,MAAA,IAAW,EAAL,gBAAK,CAAA,IAAA,EAAA,OAAA,CAAA,CAAL,KAAgB,YAAK,CAAA,IAAA,EAAA,MAAA,CAAA,OAAa,GAAI,EAAA;AAC5C,MAAA,IAAI,YAAK,CAAA,IAAA,EAAA,UAAA,CAAA,EAAiB,YAAA,CAAA,IAAA,EAAA,UAAA,CAAA,CAAW,OAAQ,EAAA;AAC7C,MAAO,OAAA,EAAE,IAAM,EAAA,KAAA,EAAO,KAAM,EAAA;AAAA;AAI7B,IAAA,IAAI,mBAAK,MAAQ,CAAA,EAAA;AAChB,MAAA,IAAI,YAAK,CAAA,IAAA,EAAA,UAAA,CAAA,EAAyB,YAAA,CAAA,YAAA,CAAA,IAAA,EAAK,UAAU,CAAA,CAAA;AACjD,MAAA,OAAO,EAAE,IAAA,EAAM,IAAM,EAAA,KAAA,EAAO,KAAmB,CAAA,EAAA;AAAA;AAIhD,IAAO,OAAA,IAAI,OAA2B,CAAA,CAAC,OAAY,KAAA;AAClD,MAAA,IAAI,SAA+C,GAAA,IAAA;AAInD,MAAA,IAAI,mBAAK,KAAO,CAAA,EAAA;AACf,QAAA,SAAA,GAAY,WAAW,MAAM;AAC5B,UAAA,IAAA,CAAK,GAAI,EAAA;AACT,UAAQ,OAAA,CAAA,IAAA,CAAK,MAAM,CAAA;AAAA,SACpB,EAAG,mBAAK,KAAK,CAAA,CAAA;AAAA;AAKd,MAAA,IAAA,CAAK,OAAQ,CAAA,IAAA,CAAK,IAAK,CAAA,KAAA,EAAO,MAAM;AACnC,QAAI,IAAA,SAAA,eAAwB,SAAS,CAAA;AACrC,QAAQ,OAAA,CAAA,IAAA,CAAK,MAAM,CAAA;AAAA,OACnB,CAAA;AAAA,KACD,CAAA;AAAA;AACF;AAAA;AAAA;AAAA,EAKO,MAAqC,GAAA;AAC3C,IAAA,IAAA,CAAK,GAAI,EAAA;AACT,IAAA,OAAO,QAAQ,OAAQ,CAAA,EAAE,MAAM,IAAM,EAAA,KAAA,EAAO,QAAoB,CAAA;AAAA;AACjE;AAAA;AAAA;AAAA,EAKO,KAAoC,GAAA;AAC1C,IAAA,IAAA,CAAK,GAAI,EAAA;AACT,IAAA,OAAO,QAAQ,OAAQ,CAAA,EAAE,MAAM,IAAM,EAAA,KAAA,EAAO,QAAoB,CAAA;AAAA;AACjE;AAAA;AAAA;AAAA,EAKA,CAAQ,MAAO,CAAA,aAAa,CAA8B,GAAA;AACzD,IAAO,OAAA,IAAA;AAAA;AACR;AAAA;AAAA;AAAA,EAKU,QAAQ,KAAgB,EAAA;AACjC,IAAK,YAAA,CAAA,IAAA,EAAA,MAAA,CAAA,CAAO,KAAK,KAAK,CAAA;AAAA;AAExB,CAAA;AAhJC,MAAA,GAAA,IAAA,OAAA,EAAA;AAKS,KAAA,GAAA,IAAA,OAAA,EAAA;AAKT,MAAA,GAAA,IAAA,OAAA,EAAA;AAKA,OAAA,GAAA,IAAA,OAAA,EAAA;AAKS,MAAA,GAAA,IAAA,OAAA,EAAA;AAKA,UAAA,GAAA,IAAA,OAAA,EAAA;AAKA,KAAA,GAAA,IAAA,OAAA,EAAA;AAjD0E,MAAA,CAAA,cAAA,EAAA,eAAA,CAAA;AAA7E,IAAM,aAAN,GAAA","file":"index.cjs","sourcesContent":["import type { EventEmitter } from 'node:events';\n\n/**\n * A filter for an EventIterator.\n */\nexport type EventIteratorFilter<V> = (value: V) => boolean;\n\n/**\n * Options to be passed to an EventIterator.\n */\nexport interface EventIteratorOptions<V> {\n\t/**\n\t * The filter.\n\t */\n\tfilter?: EventIteratorFilter<V>;\n\n\t/**\n\t * The timeout in ms before ending the EventIterator.\n\t */\n\tidle?: number;\n\n\t/**\n\t * The limit of events that pass the filter to iterate.\n\t */\n\tlimit?: number;\n}\n\n/**\n * An EventIterator, used for asynchronously iterating over received values.\n */\nexport class EventIterator<V extends unknown[]> implements AsyncIterableIterator<V> {\n\t/**\n\t * The emitter to listen to.\n\t */\n\tpublic readonly emitter: EventEmitter;\n\n\t/**\n\t * The event the event iterator is listening for to receive values from.\n\t */\n\tpublic readonly event: string;\n\n\t/**\n\t * The filter used to filter out values.\n\t */\n\tpublic filter: EventIteratorFilter<V>;\n\n\t/**\n\t * Whether or not the EventIterator has ended.\n\t */\n\t#ended = false;\n\n\t/**\n\t * The amount of idle time in ms before moving on.\n\t */\n\treadonly #idle?: number;\n\n\t/**\n\t * The queue of received values.\n\t */\n\t#queue: V[] = [];\n\n\t/**\n\t * The amount of events that have passed the filter.\n\t */\n\t#passed = 0;\n\n\t/**\n\t * The limit before ending the EventIterator.\n\t */\n\treadonly #limit: number;\n\n\t/**\n\t * The timer to track when this will idle out.\n\t */\n\treadonly #idleTimer: NodeJS.Timeout | undefined | null = null;\n\n\t/**\n\t * The push handler with context bound to the instance.\n\t */\n\treadonly #push: (this: EventIterator<V>, ...value: V) => void;\n\n\t/**\n\t * @param emitter The event emitter to listen to.\n\t * @param event The event we're listening for to receives values from.\n\t * @param options Any extra options.\n\t */\n\tpublic constructor(emitter: EventEmitter, event: string, options: EventIteratorOptions<V> = {}) {\n\t\tthis.emitter = emitter;\n\t\tthis.event = event;\n\t\tthis.#limit = options.limit ?? Infinity;\n\t\tthis.#idle = options.idle;\n\t\tthis.filter = options.filter ?? ((): boolean => true);\n\n\t\t// This timer is to idle out on lack of valid responses\n\t\tif (this.#idle) this.#idleTimer = setTimeout(this.end.bind(this), this.#idle);\n\n\t\tthis.#push = this.push.bind(this);\n\t\tconst maxListeners = this.emitter.getMaxListeners();\n\t\tif (maxListeners !== 0) this.emitter.setMaxListeners(maxListeners + 1);\n\n\t\tthis.emitter.on(this.event, this.#push);\n\t}\n\n\t/**\n\t * Whether or not the EventIterator has ended.\n\t */\n\tpublic get ended(): boolean {\n\t\treturn this.#ended;\n\t}\n\n\t/**\n\t * Ends the EventIterator.\n\t */\n\tpublic end(): void {\n\t\tif (this.#ended) return;\n\t\tthis.#ended = true;\n\t\tthis.#queue = [];\n\n\t\tthis.emitter.off(this.event, this.#push);\n\t\tconst maxListeners = this.emitter.getMaxListeners();\n\t\tif (maxListeners !== 0) this.emitter.setMaxListeners(maxListeners - 1);\n\t}\n\n\t/**\n\t * The next value that's received from the EventEmitter.\n\t */\n\tpublic async next(): Promise<IteratorResult<V>> {\n\t\t// If there are elements in the queue, return an undone response:\n\t\tif (this.#queue.length) {\n\t\t\tconst value = this.#queue.shift()!;\n\t\t\tif (!this.filter(value)) return this.next();\n\t\t\tif (++this.#passed >= this.#limit) this.end();\n\t\t\tif (this.#idleTimer) this.#idleTimer.refresh();\n\t\t\treturn { done: false, value };\n\t\t}\n\n\t\t// If the iterator ended, clean-up timer and return a done response:\n\t\tif (this.#ended) {\n\t\t\tif (this.#idleTimer) clearTimeout(this.#idleTimer);\n\t\t\treturn { done: true, value: undefined as never };\n\t\t}\n\n\t\t// Listen for a new element from the emitter:\n\t\treturn new Promise<IteratorResult<V>>((resolve) => {\n\t\t\tlet idleTimer: NodeJS.Timeout | undefined | null = null;\n\n\t\t\t// If there is an idle time set, we will create a temporary timer,\n\t\t\t// which will cause the iterator to end if no new elements are received:\n\t\t\tif (this.#idle) {\n\t\t\t\tidleTimer = setTimeout(() => {\n\t\t\t\t\tthis.end();\n\t\t\t\t\tresolve(this.next());\n\t\t\t\t}, this.#idle);\n\t\t\t}\n\n\t\t\t// Once it has received at least one value, we will clear the timer (if defined),\n\t\t\t// and resolve with the new value:\n\t\t\tthis.emitter.once(this.event, () => {\n\t\t\t\tif (idleTimer) clearTimeout(idleTimer);\n\t\t\t\tresolve(this.next());\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Handles what happens when you break or return from a loop.\n\t */\n\tpublic return(): Promise<IteratorResult<V>> {\n\t\tthis.end();\n\t\treturn Promise.resolve({ done: true, value: undefined as never });\n\t}\n\n\t/**\n\t * Handles what happens when you encounter an error in a loop.\n\t */\n\tpublic throw(): Promise<IteratorResult<V>> {\n\t\tthis.end();\n\t\treturn Promise.resolve({ done: true, value: undefined as never });\n\t}\n\n\t/**\n\t * The symbol allowing EventIterators to be used in for-await-of loops.\n\t */\n\tpublic [Symbol.asyncIterator](): AsyncIterableIterator<V> {\n\t\treturn this;\n\t}\n\n\t/**\n\t * Pushes a value into the queue.\n\t */\n\tprotected push(...value: V): void {\n\t\tthis.#queue.push(value);\n\t}\n}\n"]}