runPool<T>() bounded async worker pool

TypeScript
export type PoolResult<T> =
  | { status: 'fulfilled'; value: T }
  | { status: 'rejected'; reason: unknown };

/** Run promise-returning tasks with a fixed concurrency, preserving task order. */
export async function runPool<T>(tasks: readonly (() => Promise<T>)[], concurrency = 4): Promise<PoolResult<T>[]> {
  const size = Math.max(1, Math.min(concurrency, tasks.length));
  const results: PoolResult<T>[] = new Array(tasks.length);
  const queue = tasks.map((task, index) => ({ task, index }));
  const worker = async (): Promise<void> => {
    for (;;) {
      const next = queue.shift();
      if (next === undefined) return;
      try {
        results[next.index] = { status: 'fulfilled', value: await next.task() };
      } catch (reason) {
        results[next.index] = { status: 'rejected', reason };
      }
    }
  };
  await Promise.all(Array.from({ length: size }, () => worker()));
  return results;
}

// const pages = await runPool(urls.map((url) => () => getJson(url)), 8);