import type { AbortableAsyncMapper, AbortableAsyncPredicate, AbortableMapper, AbortablePredicate, Promisable, } from '../types.js' import { END, SKIP } from '../types.js' /** * Similar to Iterable2, but for AsyncIterable. * * AsyncIterable2 is a wrapper around AsyncIterable that implements "Iterator Helpers proposal": * https://github.com/tc39/proposal-iterator-helpers * * AsyncIterable2 can be removed after the proposal is widely implemented in Node & browsers. * * @experimental */ export class AsyncIterable2 implements AsyncIterable { private constructor(private it: AsyncIterable) {} static of(it: AsyncIterable): AsyncIterable2 { return new AsyncIterable2(it) } static ofIterable(it: Iterable): AsyncIterable2 { return new AsyncIterable2({ async *[Symbol.asyncIterator]() { yield* it }, }) } static empty(): AsyncIterable2 { return new AsyncIterable2({ async *[Symbol.asyncIterator]() {}, }) } [Symbol.asyncIterator](): AsyncIterator { return this.it[Symbol.asyncIterator]() } async toArray(): Promise { // todo: Array.fromAsync is not yet available, use that when it's ready // return await Array.fromAsync(this.it) const res: T[] = [] for await (const item of this.it) { res.push(item) } return res } async forEach(cb: (v: T, i: number) => Promisable): Promise { let i = 0 for await (const v of this.it) { if ((await cb(v, i++)) === END) return } } async some(cb: AbortableAsyncPredicate): Promise { return !!(await this.find(cb)) } async someSync(cb: AbortablePredicate): Promise { return !!(await this.findSync(cb)) } async every(cb: AbortableAsyncPredicate): Promise { let i = 0 for await (const v of this.it) { const r = await cb(v, i++) if (r === END || !r) return false } return true } async everySync(cb: AbortablePredicate): Promise { let i = 0 for await (const v of this.it) { const r = cb(v, i++) if (r === END || !r) return false } return true } async find(cb: AbortableAsyncPredicate): Promise { let i = 0 for await (const v of this.it) { const r = await cb(v, i++) if (r === END) return if (r) return v } } async findSync(cb: AbortablePredicate): Promise { let i = 0 for await (const v of this.it) { const r = cb(v, i++) if (r === END) return if (r) return v } } filter(cb: AbortableAsyncPredicate): AsyncIterable2 { const { it } = this return new AsyncIterable2({ async *[Symbol.asyncIterator]() { let i = 0 for await (const v of it) { const r = await cb(v, i++) if (r === END) return if (r) yield v } }, }) } filterSync(cb: AbortablePredicate): AsyncIterable2 { const { it } = this return new AsyncIterable2({ async *[Symbol.asyncIterator]() { let i = 0 for await (const v of it) { const r = cb(v, i++) if (r === END) return if (r) yield v } }, }) } map(mapper: AbortableAsyncMapper): AsyncIterable2 { const { it } = this return new AsyncIterable2({ async *[Symbol.asyncIterator]() { let i = 0 for await (const v of it) { const r = await mapper(v, i++) if (r === END) return if (r === SKIP) continue yield r } }, }) } mapSync(mapper: AbortableMapper): AsyncIterable2 { const { it } = this return new AsyncIterable2({ async *[Symbol.asyncIterator]() { let i = 0 for await (const v of it) { const r = mapper(v, i++) if (r === END) return if (r === SKIP) continue yield r } }, }) } }