// SPEC-597-EXEMPT: canonical mapping (npm-package↔framework, keyword catalogue)
// — must enumerate framework names by design; no detection logic to migrate.
// engine/detectors/deployment-detector.ts — Deployment config detection (SPEC-026a)
// Detects deployment targets, IaC tools, container orchestration, and cloud configs.
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { glob } from 'glob';
// === Detection signals ===
const DEPLOYMENT_SIGNALS = [
    {
        target: 'vercel',
        paths: ['vercel.json', '.vercel/project.json'],
        globPatterns: ['vercel.json'],
    },
    {
        target: 'netlify',
        paths: ['netlify.toml', '_redirects', '.netlify'],
    },
    {
        target: 'fly-io',
        paths: ['fly.toml'],
    },
    {
        target: 'railway',
        paths: ['railway.json', 'railway.toml'],
    },
    {
        target: 'render',
        paths: ['render.yaml', 'render.yml'],
    },
    {
        target: 'heroku',
        paths: ['Procfile', 'app.json'],
    },
    {
        target: 'cloudflare-pages',
        paths: ['wrangler.toml', 'wrangler.json', '.cloudflare/workers-site'],
    },
    {
        target: 'github-pages',
        paths: [],
        globPatterns: ['.github/workflows/*pages*.yml', '.github/workflows/*deploy*.yml'],
    },
    {
        target: 'kubernetes',
        paths: [],
        globPatterns: ['k8s/**/*.yaml', 'kubernetes/**/*.yaml', 'k8s/**/*.yml'],
    },
    {
        target: 'docker-compose',
        paths: ['docker-compose.yml', 'docker-compose.yaml', 'compose.yml', 'compose.yaml'],
    },
    {
        target: 'aws',
        paths: ['cdk.json', 'cdk.context.json', 'amplify.yml', '.aws'],
        globPatterns: ['cloudformation*.yaml', 'cloudformation*.yml', 'template.yaml'],
    },
    {
        target: 'gcp',
        paths: ['app.yaml', '.gcloudignore', 'cloudbuild.yaml'],
    },
    {
        target: 'azure',
        paths: ['.azure', 'azure.yaml'],
        globPatterns: ['azure-deploy*.json', 'azuredeploy.json'],
    },
    {
        target: 'digitalocean',
        paths: ['.do/app.yaml', '.do/deploy.template.yaml'],
    },
];
const IAC_TOOLS = [
    { tool: 'terraform', paths: [] },
    { tool: 'pulumi', paths: ['Pulumi.yaml', 'Pulumi.yml'] },
    { tool: 'cdk', paths: ['cdk.json'] },
    { tool: 'ansible', paths: ['ansible.cfg', 'playbook.yml', 'site.yml'] },
    { tool: 'helm', paths: ['Chart.yaml'] },
];
const TERRAFORM_PATTERN = '**/*.tf';
const HELM_PATTERN = '**/Chart.yaml';
// === Public API ===
/**
 * Detects deployment configuration in a project.
 */
export async function detectDeployment(projectPath) {
    const targets = [];
    const configFiles = [];
    for (const signal of DEPLOYMENT_SIGNALS) {
        const files = await findDeploymentFiles(projectPath, signal);
        if (files.length > 0) {
            targets.push(signal.target);
            configFiles.push(...files);
        }
    }
    // IaC detection
    const iacTools = [];
    for (const iac of IAC_TOOLS) {
        const found = await hasAnyPaths(projectPath, iac.paths);
        if (found) {
            iacTools.push(iac.tool);
        }
    }
    // Terraform — glob for .tf files
    const hasTerraform = await hasGlobMatches(projectPath, TERRAFORM_PATTERN);
    if (hasTerraform && !iacTools.includes('terraform')) {
        iacTools.push('terraform');
    }
    // Helm — glob for Chart.yaml
    const hasHelm = await hasGlobMatches(projectPath, HELM_PATTERN);
    if (hasHelm) {
        iacTools.push('helm');
    }
    return {
        targets,
        hasInfraAsCode: iacTools.length > 0,
        iacTools,
        hasDockerCompose: targets.includes('docker-compose'),
        hasKubernetes: targets.includes('kubernetes'),
        hasHelmChart: iacTools.includes('helm'),
        configFiles: [...new Set(configFiles)],
    };
}
// === Internal helpers ===
async function findDeploymentFiles(projectPath, signal) {
    const found = [];
    for (const p of signal.paths) {
        if (await fileExists(join(projectPath, p))) {
            found.push(p);
        }
    }
    if (signal.globPatterns) {
        for (const pattern of signal.globPatterns) {
            try {
                const matches = await glob(pattern, { cwd: projectPath, nodir: true });
                found.push(...matches);
            }
            catch {
                // ignore
            }
        }
    }
    return found;
}
async function hasAnyPaths(projectPath, paths) {
    for (const p of paths) {
        if (await fileExists(join(projectPath, p))) {
            return true;
        }
    }
    return false;
}
async function hasGlobMatches(projectPath, pattern) {
    try {
        const matches = await glob(pattern, { cwd: projectPath, nodir: true });
        return matches.length > 0;
    }
    catch {
        return false;
    }
}
async function fileExists(filePath) {
    try {
        await readFile(filePath, 'utf-8');
        return true;
    }
    catch {
        return false;
    }
}
//# sourceMappingURL=deployment-detector.js.map