export function streamiterator(stream: PromiseLike): AsyncGenerator export function streamiterator(stream: Body): AsyncGenerator export function streamiterator(stream: ReadableStream): AsyncGenerator export function streamiterator(stream: ReadableStreamDefaultReader): AsyncGenerator export function streamiterator(stream: Blob): AsyncGenerator export function streamiterator(stream: AsyncIterable): AsyncGenerator export function streamiterator(stream: Iterable | T>): AsyncGenerator export async function* streamiterator( stream: | PromiseLike | Body | ReadableStream | ReadableStreamDefaultReader | Blob | Iterable | T> | AsyncIterable, ): AsyncGenerator { const resolved = await stream const reader = getStream(resolved) ?? getStream((resolved as Body)?.body) if (!reader) { throw new TypeError("argument is not a ReadableStream") } else if (isIterable(reader)) { // do not use async iteration over sync iterator // https://github.com/tc39/ecma262/issues/1849 for (const chunk of reader) yield chunk } else if (isAsyncIterable(reader)) { for await (const chunk of reader) yield chunk } else if (isReader(reader)) { let needClose try { for (;;) { needClose = true const x = await reader.read() if (x.done) break needClose = false yield x.value } } finally { if (!needClose) await reader.cancel?.() } } else { throw new TypeError("argument is not a ReadableStream") } } function getStream(value: unknown): Iterable | AsyncIterable | ReadableStreamDefaultReader | undefined { if (!value) { return undefined } if (isReadable(value)) { return value } if (isReadableStream(value)) { return value.getReader() } if (isBlob(value)) { return value.stream()?.getReader?.() } return undefined } function isIterable(value: unknown): value is Iterable { return typeof (value as Iterable)[Symbol.iterator] === "function" } function isAsyncIterable(value: unknown): value is AsyncIterable { return typeof (value as AsyncIterable)[Symbol.asyncIterator] === "function" } function isReadableStream(value: unknown): value is ReadableStream { return typeof (value as ReadableStream).getReader === "function" } function isBlob(value: unknown): value is Blob { return typeof (value as Blob).stream === "function" } function isReader(value: unknown): value is ReadableStreamDefaultReader { return typeof (value as ReadableStreamDefaultReader).read === "function" } function isReadable(value: unknown): value is Iterable | AsyncIterable | ReadableStreamDefaultReader { return isIterable(value) || isAsyncIterable(value) || isReader(value) }