summaryrefslogtreecommitdiff
path: root/src/utils/iterator.ts
diff options
context:
space:
mode:
authorJoão Augusto Costa Branco Marado Torres <torres.dev@disroot.org>2025-06-24 12:08:41 -0300
committerJoão Augusto Costa Branco Marado Torres <torres.dev@disroot.org>2025-06-24 12:50:43 -0300
commitf9a77c5c27aede4e5978eb55d9b7af781b680a1d (patch)
treed545e325ba1ae756fc2eac66fac1001b6753c40d /src/utils/iterator.ts
feat!: initial commit
Signed-off-by: João Augusto Costa Branco Marado Torres <torres.dev@disroot.org>
Diffstat (limited to 'src/utils/iterator.ts')
-rw-r--r--src/utils/iterator.ts52
1 files changed, 52 insertions, 0 deletions
diff --git a/src/utils/iterator.ts b/src/utils/iterator.ts
new file mode 100644
index 0000000..fa58fc9
--- /dev/null
+++ b/src/utils/iterator.ts
@@ -0,0 +1,52 @@
+export type MaybeIterable<T> = T | Iterable<T>;
+export type NonEmptyArray<T> = [T, ...T[]];
+export type AsyncYieldType<T> = T extends AsyncGenerator<infer U> ? U : never;
+
+export function surelyIterable<T>(maybe: MaybeIterable<T>): Iterable<T> {
+ return typeof maybe === "object" && maybe !== null && Symbol.iterator in maybe
+ ? maybe
+ : [maybe];
+}
+
+export async function* createAsyncIterator<T>(
+ promises: Promise<T>[],
+): AsyncGenerator<T, void, void> {
+ for (const promise of promises) {
+ yield promise;
+ }
+}
+
+export function filterDuplicate<T, K>(
+ array: Iterable<T>,
+ key: (i: T) => K,
+): T[] {
+ const seen = new Map<K, T>();
+ 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<T, R>(
+ iter: Iterable<T>,
+ predicate: (value: T) => Promise<R>,
+): Promise<R | undefined> {
+ const arr = Array.from(iter);
+
+ async function tryNext(index: number): Promise<R | undefined> {
+ if (index >= arr.length) {
+ return await Promise.resolve(undefined);
+ }
+
+ try {
+ return await predicate(arr[index]);
+ } catch {
+ return tryNext(index + 1);
+ }
+ }
+
+ return await tryNext(0);
+}