// SPEC-597-EXEMPT: canonical mapping (npm-package↔framework, keyword catalogue)
// — must enumerate framework names by design; no detection logic to migrate.
// ci-generator/stack-detector.ts — Detect project stack for CI generation (SPEC-066)
import { readFile, access } from 'node:fs/promises';
import { join } from 'node:path';
// -- File existence helper ---------------------------------------------------
async function fileExists(filePath) {
    try {
        await access(filePath);
        return true;
    }
    catch {
        return false;
    }
}
async function readTextSafe(filePath) {
    try {
        return await readFile(filePath, 'utf-8');
    }
    catch {
        return '';
    }
}
async function readJsonSafe(filePath) {
    try {
        const content = await readFile(filePath, 'utf-8');
        return JSON.parse(content);
    }
    catch {
        return null;
    }
}
// -- Ecosystem detection -----------------------------------------------------
export async function detectEcosystem(projectPath) {
    if (await fileExists(join(projectPath, 'go.mod'))) {
        return 'go';
    }
    if (await fileExists(join(projectPath, 'Cargo.toml'))) {
        return 'rust';
    }
    if (await fileExists(join(projectPath, 'pom.xml'))) {
        return 'java';
    }
    if (await fileExists(join(projectPath, 'build.gradle'))) {
        return 'java';
    }
    if (await fileExists(join(projectPath, 'build.gradle.kts'))) {
        return 'kotlin';
    }
    if (await fileExists(join(projectPath, 'Gemfile'))) {
        return 'ruby';
    }
    if (await fileExists(join(projectPath, 'composer.json'))) {
        return 'php';
    }
    if (await fileExists(join(projectPath, 'pubspec.yaml'))) {
        return 'dart';
    }
    if (await fileExists(join(projectPath, 'package.json'))) {
        return 'nodejs';
    }
    if ((await fileExists(join(projectPath, 'pyproject.toml'))) ||
        (await fileExists(join(projectPath, 'requirements.txt'))) ||
        (await fileExists(join(projectPath, 'setup.py')))) {
        return 'python';
    }
    if (await fileExists(join(projectPath, 'global.json'))) {
        return 'dotnet';
    }
    return 'unknown';
}
// -- Node.js helpers ---------------------------------------------------------
export async function detectNodePackageManager(projectPath) {
    if (await fileExists(join(projectPath, 'pnpm-lock.yaml'))) {
        return 'pnpm';
    }
    if (await fileExists(join(projectPath, 'bun.lockb'))) {
        return 'bun';
    }
    if (await fileExists(join(projectPath, 'yarn.lock'))) {
        return 'yarn';
    }
    return 'npm';
}
export async function detectNodeVersion(projectPath) {
    const nvmrc = await readTextSafe(join(projectPath, '.nvmrc'));
    if (nvmrc.trim()) {
        return nvmrc.trim();
    }
    const nodeVer = await readTextSafe(join(projectPath, '.node-version'));
    if (nodeVer.trim()) {
        return nodeVer.trim();
    }
    const pkg = await readJsonSafe(join(projectPath, 'package.json'));
    if (pkg) {
        const engines = pkg.engines;
        if (engines?.node) {
            const match = /(\d+)/.exec(engines.node);
            return match?.[1] ?? '20';
        }
    }
    return '20';
}
export function buildNodeCommands(pm) {
    const run = pm === 'npm' ? 'npm run' : pm === 'bun' ? 'bun run' : `${pm} run`;
    const install = pm === 'pnpm'
        ? 'pnpm install --frozen-lockfile'
        : pm === 'yarn'
            ? 'yarn install --frozen-lockfile'
            : pm === 'bun'
                ? 'bun install --frozen-lockfile'
                : 'npm ci';
    return { install, lint: `${run} lint`, test: `${run} test`, build: `${run} build` };
}
// -- Python helpers ----------------------------------------------------------
export async function detectPythonPackageManager(projectPath) {
    const pyproject = await readTextSafe(join(projectPath, 'pyproject.toml'));
    if (pyproject.includes('[tool.poetry]')) {
        return 'poetry';
    }
    if (await fileExists(join(projectPath, 'uv.lock'))) {
        return 'uv';
    }
    return 'pip';
}
export async function detectPythonVersion(projectPath) {
    const pyVer = await readTextSafe(join(projectPath, '.python-version'));
    if (pyVer.trim()) {
        return pyVer.trim();
    }
    const pyproject = await readTextSafe(join(projectPath, 'pyproject.toml'));
    if (pyproject) {
        const match = /requires-python\s*=\s*"([^"]+)"/.exec(pyproject);
        if (match?.[1]) {
            const verMatch = /(\d+\.\d+)/.exec(match[1]);
            return verMatch?.[1] ?? '3.11';
        }
    }
    return '3.11';
}
// -- Go helpers --------------------------------------------------------------
export async function detectGoVersion(projectPath) {
    const goMod = await readTextSafe(join(projectPath, 'go.mod'));
    const match = /^go\s+(\S+)/m.exec(goMod);
    return match?.[1] ?? '1.22';
}
// -- Rust helpers ------------------------------------------------------------
export async function detectRustChannel(projectPath) {
    const toolchain = await readTextSafe(join(projectPath, 'rust-toolchain.toml'));
    if (toolchain) {
        const match = /channel\s*=\s*"([^"]+)"/.exec(toolchain);
        if (match?.[1]) {
            return match[1];
        }
    }
    const toolchainFile = await readTextSafe(join(projectPath, 'rust-toolchain'));
    if (toolchainFile.trim()) {
        return toolchainFile.trim();
    }
    return 'stable';
}
// -- Java helpers ------------------------------------------------------------
export async function detectJavaVersion(projectPath) {
    const pom = await readTextSafe(join(projectPath, 'pom.xml'));
    if (pom) {
        const match = /<java.version>([^<]+)</.exec(pom) ?? /<maven.compiler.source>([^<]+)</.exec(pom);
        if (match?.[1]) {
            return match[1];
        }
    }
    for (const gradleFile of ['build.gradle.kts', 'build.gradle']) {
        const gradle = await readTextSafe(join(projectPath, gradleFile));
        if (gradle) {
            const match = /(?:sourceCompatibility|jvmTarget)\s*[=:]\s*['"]?(\S+?)['"]?\s/m.exec(gradle);
            if (match?.[1]) {
                return match[1];
            }
        }
    }
    return '21';
}
export async function detectJavaBuildTool(projectPath) {
    if (await fileExists(join(projectPath, 'pom.xml'))) {
        return 'maven';
    }
    return 'gradle';
}
// -- Docker detection --------------------------------------------------------
export async function detectHasDocker(projectPath) {
    return ((await fileExists(join(projectPath, 'Dockerfile'))) ||
        (await fileExists(join(projectPath, 'docker-compose.yml'))) ||
        (await fileExists(join(projectPath, 'docker-compose.yaml'))));
}
// detectCIStack moved to context-builders.ts to break circular dependency
//# sourceMappingURL=stack-detector.js.map