function extractProjectRef(projectUrl) {
    // https://abc123.supabase.co → abc123
    const match = /https?:\/\/([^.]+)\.supabase\.co/.exec(projectUrl);
    if (!match?.[1]) {
        throw new Error(`Cannot extract project ref from URL: ${projectUrl}`);
    }
    return match[1];
}
function buildColumnFromProperty(name, prop, requiredFields, primaryKeys) {
    const nullable = !requiredFields.includes(name);
    const defaultValue = prop.default !== undefined && prop.default !== null ? String(prop.default) : undefined;
    return {
        name,
        type: prop.format ?? prop.type ?? 'unknown',
        nullable,
        isPrimaryKey: primaryKeys.has(name),
        isForeignKey: false,
        defaultValue,
    };
}
function inferPrimaryKeys(def) {
    const keys = new Set();
    // Supabase OpenAPI marks PK via description containing "Primary Key"
    if (!def.properties) {
        return keys;
    }
    for (const [name, prop] of Object.entries(def.properties)) {
        if (typeof prop.description === 'string' && prop.description.includes('Primary Key')) {
            keys.add(name);
        }
    }
    // Fallback: if no PK found and there's an 'id' column, treat it as PK
    if (keys.size === 0 && 'id' in def.properties) {
        keys.add('id');
    }
    return keys;
}
function definitionToTable(name, def) {
    const required = def.required ?? [];
    const primaryKeys = inferPrimaryKeys(def);
    const columns = [];
    if (def.properties) {
        for (const [colName, prop] of Object.entries(def.properties)) {
            columns.push(buildColumnFromProperty(colName, prop, required, primaryKeys));
        }
    }
    return {
        name,
        schema: 'public',
        columns,
        rlsPolicies: [],
        hasRls: false,
    };
}
export async function fetchTables(config, schemas) {
    const url = `${config.projectUrl}/rest/v1/?apikey=${config.serviceRoleKey}`;
    const res = await fetch(url, {
        headers: {
            apikey: config.serviceRoleKey,
            Authorization: `Bearer ${config.serviceRoleKey}`,
        },
    });
    if (!res.ok) {
        const body = await res.text();
        throw new Error(`Supabase OpenAPI error ${res.status}: ${body}`);
    }
    const spec = (await res.json());
    const definitions = spec.definitions ?? {};
    const tables = [];
    for (const [name, def] of Object.entries(definitions)) {
        // Filter by schema — Supabase OpenAPI only returns public tables in definitions
        if (schemas.length > 0 && !schemas.includes('public')) {
            continue;
        }
        tables.push(definitionToTable(name, def));
    }
    return tables;
}
function normalizeOperation(cmd) {
    const upper = cmd.toUpperCase();
    if (upper === 'SELECT') {
        return 'SELECT';
    }
    if (upper === 'INSERT') {
        return 'INSERT';
    }
    if (upper === 'UPDATE') {
        return 'UPDATE';
    }
    if (upper === 'DELETE') {
        return 'DELETE';
    }
    return 'ALL';
}
export async function fetchRlsPolicies(config) {
    const projectRef = extractProjectRef(config.projectUrl);
    const url = `https://api.supabase.com/v1/projects/${projectRef}/database/policies`;
    try {
        const res = await fetch(url, {
            headers: {
                Authorization: `Bearer ${config.serviceRoleKey}`,
            },
        });
        if (!res.ok) {
            // Management API keys differ from service role keys — silently return empty
            return [];
        }
        const policies = (await res.json());
        return policies.map((p) => ({
            name: p.name,
            table: p.table,
            operation: normalizeOperation(p.command),
            using: p.definition,
            withCheck: p.check,
            roles: p.roles ?? [],
        }));
    }
    catch {
        // Network error or non-management key — silently return empty
        return [];
    }
}
//# sourceMappingURL=schema-fetcher.js.map