import {pushable, Pushable} from "it-pushable"; export async function * mapAsync(stream: AsyncIterable, mapFn: (value: T) => U | PromiseLike): AsyncGenerator { for await (const event of stream) { yield await mapFn(event); } } export async function * cloneAsync(stream: AsyncIterable, target: Pushable): AsyncGenerator { for await (const event of stream) { target.push(event); yield event; } } export async function * joinAsync(stream: AsyncIterable, separator?:string ): AsyncGenerator { return mapAsync(stream, (value) => value.join(separator)); } export async function * splitAsync(stream: AsyncIterable, ...separator: string[]): AsyncGenerator { let buffer = ''; for await (const event of stream) { buffer += event; const s=separator.filter(s=>event.includes(s)); if(s.length > 0) { const parts = buffer.split(s[0]); yield parts.join(''); } } } export async function * filterAsync(stream: AsyncIterable, filterFn: (value: T) => value is TFiltered ): AsyncGenerator { for await (const event of stream) { if (filterFn(event)) { yield event; } } } export async function* castAsync(e: AsyncIterable) { for await (const value of e) { yield value as T; } } export type BatchAsyncParams={stream: AsyncIterable, split?:(i:T)=> boolean} export async function * batchAsync< T extends any,TIterable extends AsyncIterable=AsyncIterable>(stream: TIterable, split?:(current:T, buffer:T[])=> boolean ): AsyncGenerator { const buffer:T[] = []; for await (const event of stream) { buffer.push(event); if (typeof split == "undefined" || split(event, buffer)) { yield buffer.splice(0, buffer.length - 1) } } } export async function * delayAsync(stream: AsyncIterable, ms= 50): AsyncGenerator { for await (const value of stream) { await new Promise((resolve) => setTimeout(resolve, ms)); yield value; } } /* in use? */ export function teeAsync(stream: AsyncIterable): [AsyncIterable,AsyncIterable] { const target = pushable({objectMode: true}) ; return [cloneAsync(stream, target), target[Symbol.asyncIterator]()]; } export function teePushableAsync(stream: Pushable): [AsyncIterable, Pushable] { const target = pushable({objectMode: true}) ; return [cloneAsync(stream, target), target]; } export function concatAsync(...streams: AsyncIterable[]): AsyncGenerator { const p = pushable({objectMode: true}); for (const stream of streams) { cloneAsync(stream, p); } return p; } export function flatAsync(composed:AsyncGenerator>): AsyncGenerator { const p = pushable({objectMode: true}); (async () => { for await (const stream of composed) { (async () => { for await (const value of stream) { p.push(value); } })().catch(console.error); } })(); return p; }