/**
 * KeychainProvider — reads credentials from macOS Keychain via `security`.
 *
 * Tries `find-internet-password -s <host>` first; falls back to
 * `find-generic-password -s <host>` for app-scoped items. Returns the value
 * only if macOS approves (the user may see a per-item prompt the first time).
 *
 * Returns "not_found" on misses and "unsupported" on non-macOS.
 */
import { execFile } from "node:child_process";
function run(cmd, args, timeoutMs) {
    return new Promise((resolve) => {
        execFile(cmd, args, { timeout: timeoutMs, encoding: "utf-8" }, (err, stdout, stderr) => {
            const code = err && typeof err.code === "number"
                ? err.code
                : err
                    ? 1
                    : 0;
            resolve({ code, stdout: stdout ?? "", stderr: stderr ?? "" });
        });
    });
}
/**
 * Strip leading "www." so keychain items saved as "github.com" match
 * when the browser page is on "www.github.com".
 */
function normalizeHost(host) {
    const h = host.toLowerCase().trim();
    const candidates = new Set([h]);
    if (h.startsWith("www."))
        candidates.add(h.slice(4));
    else
        candidates.add(`www.${h}`);
    // Also try the registrable root for things like "accounts.google.com" -> "google.com".
    const parts = h.split(".");
    if (parts.length >= 3)
        candidates.add(parts.slice(-2).join("."));
    return Array.from(candidates);
}
export class KeychainProvider {
    constructor() {
        this.name = "macos-keychain";
    }
    async lookup(q) {
        if (process.platform !== "darwin") {
            return { ok: false, reason: "unsupported", message: "macOS Keychain is only available on darwin" };
        }
        const hosts = normalizeHost(q.host);
        for (const host of hosts) {
            // 1. Internet password (Safari / AutoFill)
            const internetArgs = ["find-internet-password", "-s", host, "-w"];
            if (q.account)
                internetArgs.splice(3, 0, "-a", q.account);
            const r1 = await run("/usr/bin/security", internetArgs, 10_000);
            if (r1.code === 0 && r1.stdout.trim()) {
                return { ok: true, value: r1.stdout.replace(/\n$/, ""), account: q.account };
            }
            // -25293 = errSecAuthFailed; user denied Touch ID / password prompt.
            if (r1.stderr.includes("-25293") || /user\s+(interaction|canceled)/i.test(r1.stderr)) {
                return { ok: false, reason: "denied", message: "macOS denied access to the keychain item" };
            }
            // 2. Generic password (apps that use the generic partition)
            const genericArgs = ["find-generic-password", "-s", host, "-w"];
            if (q.account)
                genericArgs.splice(3, 0, "-a", q.account);
            const r2 = await run("/usr/bin/security", genericArgs, 10_000);
            if (r2.code === 0 && r2.stdout.trim()) {
                return { ok: true, value: r2.stdout.replace(/\n$/, ""), account: q.account };
            }
            if (r2.stderr.includes("-25293") || /user\s+(interaction|canceled)/i.test(r2.stderr)) {
                return { ok: false, reason: "denied", message: "macOS denied access to the keychain item" };
            }
        }
        return {
            ok: false,
            reason: "not_found",
            message: `no keychain entry found for ${q.host}${q.account ? ` / ${q.account}` : ""}`,
        };
    }
}
//# sourceMappingURL=keychain.js.map