// engine/edge-db-detector.ts — SPEC-052
// Detects edge-native SQLite usage: Turso (libSQL) and Cloudflare D1.
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { glob } from 'glob';
// === Source file glob ignore list ===
const SOURCE_GLOB_IGNORE = ['node_modules/**', 'dist/**', 'build/**', '.git/**', 'coverage/**'];
// === Helpers ===
async function readFileOrNull(filePath) {
    try {
        return await readFile(filePath, 'utf-8');
    }
    catch {
        return null;
    }
}
async function readEdgeDbPackageDeps(projectPath) {
    const content = await readFileOrNull(join(projectPath, 'package.json'));
    if (!content) {
        return null;
    }
    try {
        const pkg = JSON.parse(content);
        return {
            deps: pkg.dependencies ?? {},
            devDeps: pkg.devDependencies ?? {},
        };
    }
    catch {
        return null;
    }
}
async function globSourceFiles(projectPath) {
    try {
        return await glob('**/*.{ts,js,mts,mjs,tsx,jsx}', {
            cwd: projectPath,
            nodir: true,
            maxDepth: 4,
            ignore: SOURCE_GLOB_IGNORE,
        });
    }
    catch {
        return [];
    }
}
// === S1-C1: Turso detection via @libsql/client ===
async function detectTurso(projectPath) {
    const pkgDeps = await readEdgeDbPackageDeps(projectPath);
    if (!pkgDeps) {
        return false;
    }
    return '@libsql/client' in pkgDeps.deps || '@libsql/client' in pkgDeps.devDeps;
}
// === S1-C2: Cloudflare D1 detection ===
async function detectCloudflareD1(projectPath) {
    const pkgDeps = await readEdgeDbPackageDeps(projectPath);
    if (!pkgDeps) {
        return false;
    }
    const hasWorkersTypes = '@cloudflare/workers-types' in pkgDeps.deps || '@cloudflare/workers-types' in pkgDeps.devDeps;
    if (!hasWorkersTypes) {
        return false;
    }
    // Also require D1Database usage in source files
    const hasD1Usage = await detectD1DatabaseInSource(projectPath);
    return hasD1Usage;
}
async function detectD1DatabaseInSource(projectPath) {
    const files = await globSourceFiles(projectPath);
    for (const file of files.slice(0, 40)) {
        const content = await readFileOrNull(join(projectPath, file));
        if (content?.includes('D1Database')) {
            return true;
        }
    }
    return false;
}
// === S1-C3: Embedded replica detection via createClient({ syncUrl }) ===
async function detectEmbeddedReplica(projectPath) {
    const files = await globSourceFiles(projectPath);
    for (const file of files.slice(0, 40)) {
        const content = await readFileOrNull(join(projectPath, file));
        if (!content) {
            continue;
        }
        if (hasEmbeddedReplicaSignal(content)) {
            return true;
        }
    }
    return false;
}
/**
 * Returns true when the content shows createClient called with both url and syncUrl,
 * which is the Turso embedded-replica pattern.
 */
function hasEmbeddedReplicaSignal(content) {
    // Match createClient({ ... syncUrl ... }) — presence of syncUrl key is the signal
    return /createClient\s*\(\s*\{[^}]*syncUrl/.test(content);
}
// === S4-C11: D1 migrations detection in wrangler.toml ===
async function detectD1Migrations(projectPath) {
    const content = await readFileOrNull(join(projectPath, 'wrangler.toml'));
    if (!content) {
        return false;
    }
    return content.includes('migrations_dir');
}
// === TursoMode resolution ===
async function resolveTursoMode(projectPath, isEmbeddedReplica) {
    if (isEmbeddedReplica) {
        return 'embedded-replica';
    }
    // Check for local dev signals: createClient({ url: ':memory:' }) or url: 'file:...'
    const files = await globSourceFiles(projectPath);
    for (const file of files.slice(0, 40)) {
        const content = await readFileOrNull(join(projectPath, file));
        if (!content) {
            continue;
        }
        if (/createClient\s*\(\s*\{[^}]*url\s*:\s*['"](:memory:|file:)/.test(content)) {
            return 'local';
        }
    }
    return 'remote';
}
// === Main exported function ===
/**
 * Detect edge-native database patterns (Turso/libSQL and Cloudflare D1) in a project.
 * Covers SPEC-052 criteria S1-C1, S1-C2, S1-C3, S4-C11.
 */
export async function detectEdgeDb(projectPath) {
    const [isTurso, isD1, isEmbeddedReplica] = await Promise.all([
        detectTurso(projectPath),
        detectCloudflareD1(projectPath),
        detectEmbeddedReplica(projectPath),
    ]);
    if (isTurso) {
        const tursoMode = await resolveTursoMode(projectPath, isEmbeddedReplica);
        const edgeDb = 'turso';
        return { edgeDb, tursoMode };
    }
    if (isD1) {
        const hasD1Migrations = await detectD1Migrations(projectPath);
        const edgeDb = 'cloudflare-d1';
        return { edgeDb, hasD1Migrations };
    }
    const edgeDb = 'none';
    return { edgeDb };
}
//# sourceMappingURL=edge-db-detector.js.map