/** * An AsyncGenerator that can also be awaited directly. * - `for await (const p of gen)` iterates items one at a time * - `await gen` collects all items into an array */ export type CollectableAsyncGenerator = AsyncGenerator & PromiseLike; /** Wrap an async generator to make it awaitable (collects all items on await). */ export function collectable( gen: AsyncGenerator, ): CollectableAsyncGenerator { return { [Symbol.asyncIterator]() { return gen; }, [Symbol.asyncDispose]: async () => { await gen.return(undefined as undefined); }, next: () => gen.next(), return: (v?: undefined) => gen.return(v as undefined), throw: (e: unknown) => gen.throw(e), // biome-ignore lint/suspicious/noThenProperty: intentional PromiseLike implementation then( resolve?: ((value: T[]) => TResult1 | PromiseLike) | null, reject?: ((reason: unknown) => TResult2 | PromiseLike) | null, ): Promise { return (async () => { const items: T[] = []; for await (const item of gen) items.push(item); return items; })().then(resolve, reject); }, } as CollectableAsyncGenerator; }