// `gjsify barrels` action — regenerate `index.ts` barrel files for one or
// more directories. Pure async generator, decoupled from yargs so it can
// be unit-tested in isolation.
//
// Adapted from beabee-communityrm/monorepo apps/dev-cli's `generate-index`
// action (refs/dev-cli — not vendored here): same separation of action vs.
// command module, same `types/`-dir auto-detection that emits
// `export type *`, same `export {};` fallback for empty directories,
// same sorted-output principle. Rewritten for gjsify's yargs CommandModule
// and `@gjsify/unit` test framework; no external deps. Replaces
// `barrelsby` (unmaintained since 2022) at consumer sites.
//
// Original: Copyright (c) Beabee Community Repo contributors. AGPL-3.0.
// Reimplemented for gjsify under the project's MIT license.
import { readdir, readFile, writeFile } from 'node:fs/promises';
import { basename, extname, join, resolve } from 'node:path';
export const DEFAULT_BARRELS_HEADER = '// Auto-generated by `gjsify barrels` — do not edit by hand.';
export const DEFAULT_BARRELS_EXCLUDES = ['\\.test\\.', '\\.spec\\.', '\\.test-data\\.'];
const SOURCE_FILE_RE = /\.(ts|tsx|mts|cts)$/;
/**
 * Regenerate `index.ts` in every directory in `args.paths`.
 *
 * Returns the number of files that drifted from the canonical output —
 * always 0 when `check` is false (drift is rewritten in-place); non-zero
 * under `check: true` signals CI failure.
 */
export async function generateBarrels(args) {
    const quote = args.singleQuotes ? "'" : '"';
    const semicolon = args.noSemicolon ? '' : ';';
    const extSuffix = args.extension === 'none' ? '' : `.${args.extension}`;
    let drift = 0;
    for (const p of args.paths) {
        const dir = resolve(args.baseDir, p);
        const isTypesDir = basename(dir) === 'types';
        let entries;
        try {
            entries = (await readdir(dir, { withFileTypes: true }))
                .filter((e) => e.isFile())
                .filter((e) => SOURCE_FILE_RE.test(e.name))
                .filter((e) => e.name !== 'index.ts')
                .filter((e) => !args.exclude.some((r) => r.test(e.name)))
                .sort((a, b) => a.name.localeCompare(b.name));
        }
        catch (err) {
            if (args.verbose)
                console.error(`[gjsify barrels] skip ${dir}: ${err.message}`);
            continue;
        }
        const lines = entries.map((e) => {
            const stem = basename(e.name, extname(e.name));
            const keyword = isTypesDir ? 'export type *' : 'export *';
            return `${keyword} from ${quote}./${stem}${extSuffix}${quote}${semicolon}`;
        });
        const body = lines.length ? `${lines.join('\n')}\n` : 'export {};\n';
        const out = `${args.header}\n\n${body}`;
        const indexPath = join(dir, 'index.ts');
        const previous = await readFile(indexPath, 'utf-8').catch(() => '');
        if (previous === out) {
            if (args.verbose)
                console.log(`[gjsify barrels] up-to-date: ${indexPath}`);
            continue;
        }
        if (args.check) {
            console.error(`[gjsify barrels] drift: ${indexPath}`);
            drift++;
        }
        else {
            await writeFile(indexPath, out, 'utf-8');
            if (args.verbose)
                console.log(`[gjsify barrels] wrote: ${indexPath}`);
        }
    }
    return drift;
}
