import { isFunction } from './underscore' type resolver = (x?: any) => any export interface Thenable { then (resolve: resolver, reject?: resolver): Thenable; catch (reject: resolver): Thenable; } function isThenable (val: any): val is Thenable { return val && isFunction(val.then) } function isAsyncIterator (val: any): val is IterableIterator { return val && isFunction(val.next) && isFunction(val.throw) && isFunction(val.return) } // convert an async iterator to a Promise export async function toPromise (val: Generator | Thenable | T): Promise { if (!isAsyncIterator(val)) return val let value: unknown let done = false let next = 'next' do { const state = val[next](value) done = state.done value = state.value next = 'next' try { if (isAsyncIterator(value)) value = toPromise(value) if (isThenable(value)) value = await value } catch (err) { next = 'throw' value = err } } while (!done) return value as T } // convert an async iterator to a value in a synchronous maner export function toValue (val: Generator | T): T { if (!isAsyncIterator(val)) return val let value: any let done = false let next = 'next' do { const state = val[next](value) done = state.done value = state.value next = 'next' if (isAsyncIterator(value)) { try { value = toValue(value) } catch (err) { next = 'throw' value = err } } } while (!done) return value } export const toThenable = toPromise