/**
 * @copyright Sister Software
 * @license AGPL-3.0
 * @author Teffen Ellis, et al.
 */
import { $ } from "zx";
/**
 * Given an iterable collection, returns an async iterable, executing the callback on each batch.
 *
 * This is useful for batching asynchronous operations.
 *
 * @param collection The collection to batch.
 * @param batchSize The size of each batch.
 * @param callback The async callback to execute on each batch.
 */
export async function* takeInParallel(collection, batchSize, callback, abortSignal) {
    const iterator = Symbol.asyncIterator in collection ? collection[Symbol.asyncIterator]() : collection[Symbol.iterator]();
    const runningTasks = new Map();
    const results = new Map();
    let iterationResult = await iterator.next();
    while ((!iterationResult.done || results.size) && !abortSignal?.aborted) {
        for (const [key, result] of results) {
            yield result;
            results.delete(key);
        }
        if (runningTasks.size >= batchSize) {
            await Promise.race(runningTasks.values());
            continue;
        }
        if (iterationResult.done) {
            await Promise.all(runningTasks.values());
            break;
        }
        const entry = iterationResult.value;
        const futureResult = callback(entry).then((result) => {
            runningTasks.delete(entry);
            results.set(entry, result);
        });
        runningTasks.set(entry, futureResult);
        iterationResult = await iterator.next();
    }
    if (!abortSignal || !abortSignal.aborted) {
        await Promise.all(runningTasks.values());
        for (const [key, result] of results) {
            yield result;
            results.delete(key);
        }
    }
}
/**
 * Given an async iterable collection, returns an async iterable, yielding batches of items.
 *
 * This is useful for emitting asynchronous items in batches, such as when processing a stream of
 * data.
 */
export async function* takeAsync(collection, batchSize) {
    let buffer = [];
    for await (const item of collection) {
        buffer.push(item);
        if (buffer.length === batchSize) {
            yield buffer;
            buffer = [];
        }
    }
    if (buffer.length !== 0) {
        yield buffer;
    }
}
/**
 * Given a list of file patterns, returns the count of files that match the patterns.
 */
export async function tallyPatternCount(patterns, directory) {
    const result = await $ `find ${directory} -name ${patterns.join(" -o -name ")} | wc -l`;
    return parseInt(result.stdout);
}
//# sourceMappingURL=collections.js.map