const CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" export const generateNonce = (len = 6): string => { let nonce = "" for (let i = 0; i < len; i++) { nonce += CHARS[ Math.floor(Math.random() * CHARS.length) ] } return nonce } export function hasProp(data: unknown, prop: K): data is Record { return typeof data === "object" && data != null && prop in data } export function isRecord(data: unknown): data is Record { return typeof data === "object" && data != null } export function isIterable(obj: unknown): obj is Iterable { return typeof obj === "object" && obj != null && Symbol.iterator in obj } export function isAsyncIterable(obj: unknown): obj is AsyncIterable { return typeof obj === "object" && obj != null && Symbol.asyncIterator in obj } export function all(it: Iterable): T[] export function all(it: AsyncIterable): Promise export function all(it: Iterable | AsyncIterable): T[] | Promise { if (isIterable(it)) { const arr = [] for (const elem of it) { arr.push(elem) } return arr } else if (isAsyncIterable(it)) { return (async () => { const arr = [] for await (const elem of it) { arr.push(elem) } return arr })() } else { throw new TypeError(`Expected either Iterable or AsyncIterable, but got ${it}`) } } export function first(it: Iterable): T | undefined export function first(it: AsyncIterable): Promise export function first(it: Iterable | AsyncIterable): T | undefined | Promise { if (isIterable(it)) { for (const elem of it) { return elem } return undefined } else if (isAsyncIterable(it)) { return (async () => { for await (const elem of it) { return elem } return undefined })() } else { throw new TypeError(`Expected either Iterable or AsyncIterable, but got ${it}`) } }