export type MaybeIterable = T | Iterable; export type NonEmptyArray = [T, ...T[]]; export type AsyncYieldType = T extends AsyncGenerator ? U : never; export function surelyIterable(maybe: MaybeIterable): Iterable { return typeof maybe === "object" && maybe !== null && Symbol.iterator in maybe ? maybe : [maybe]; } export async function* createAsyncIterator( promises: Promise[], ): AsyncGenerator { for (const promise of promises) { yield promise; } } export function filterDuplicate( array: Iterable, key: (i: T) => K, ): T[] { const seen = new Map(); for (const i of array) { const id = key(i); if (!seen.has(id)) { seen.set(id, i); } } return Array.from(seen.values()); } export async function findMapAsync( iter: Iterable, predicate: (value: T) => Promise, ): Promise { const arr = Array.from(iter); async function tryNext(index: number): Promise { if (index >= arr.length) { return await Promise.resolve(undefined); } try { return await predicate(arr[index]); } catch { return tryNext(index + 1); } } return await tryNext(0); }