/**
 * WebAssembly SQLite metadata index for mailx (Android/browser).
 * API-compatible with @bobfrankston/mailx-store's MailxDB.
 * Uses sql.js (SQLite compiled to WebAssembly) for in-browser SQLite.
 *
 * Database is persisted to IndexedDB on every write operation.
 * Bodies are stored in IndexedDB via WebMessageStore (not filesystem).
 */
import type { MessageEnvelope, Folder, EmailAddress, PagedResult, MessageQuery } from "@bobfrankston/mailx-types";
export declare class WebMailxDB {
    private db;
    private ready;
    private saveTimer;
    constructor(dbName?: string);
    private init;
    /** Wait for DB initialization */
    waitReady(): Promise<void>;
    /** One-shot junk-contact purge — see desktop equivalent in mailx-store/db.ts.
     *  Bump TARGET when filter rules tighten so we sweep historical rows once
     *  per device. Flag stored in localStorage (the web DB has no kv table). */
    private runOneShotJunkContactPurge;
    /** Persist DB to IndexedDB (debounced — batches rapid writes) */
    private scheduleSave;
    /** Force immediate persist */
    flush(): Promise<void>;
    close(): void;
    private run;
    private get;
    private all;
    private lastId;
    upsertAccount(id: string, name: string, email: string, configJson: string): void;
    getAccounts(): {
        id: string;
        name: string;
        email: string;
        lastSync: number;
    }[];
    getAccountConfigs(): {
        id: string;
        name: string;
        email: string;
        configJson: string;
    }[];
    updateLastSync(accountId: string, timestamp: number): void;
    upsertFolder(accountId: string, folderPath: string, name: string, specialUse: string, delimiter: string): number;
    getFolders(accountId: string): Folder[];
    deleteFolder(folderId: number): void;
    markFolderRead(folderId: number): void;
    deleteAllMessages(accountId: string, folderId: number): void;
    updateFolderCounts(folderId: number, total: number, unread: number): void;
    updateFolderSync(folderId: number, uidvalidity: number, highestModseq: string): void;
    getFolderSync(folderId: number): {
        uidvalidity: number;
        highestModseq: string;
    };
    upsertMessage(msg: {
        accountId: string;
        folderId: number;
        uid: number;
        messageId: string;
        inReplyTo: string;
        references: string[];
        date: number;
        sentDate?: number;
        subject: string;
        from: EmailAddress;
        to: EmailAddress[];
        cc: EmailAddress[];
        flags: string[];
        size: number;
        hasAttachments: boolean;
        preview: string;
        bodyPath: string;
    }): number;
    getMessages(query: MessageQuery): PagedResult<MessageEnvelope>;
    getUnifiedInbox(page?: number, pageSize?: number): PagedResult<MessageEnvelope>;
    getMessageByUid(accountId: string, uid: number, folderId?: number): MessageEnvelope;
    getMessageBodyPath(accountId: string, uid: number): string;
    /** The provider's own message id (Gmail message id) for a uid. Passed to
     *  the Gmail provider's trash/move so it doesn't fall back to a capped
     *  list-and-hash search that misses messages in a large mailbox. "" when
     *  unknown — the provider then uses its (capped) fallback. */
    getProviderId(accountId: string, uid: number): string;
    /** folderId required — see main mailx-store/db.ts for why. */
    updateMessageFlags(accountId: string, folderId: number, uid: number, flags: string[]): void;
    /** folderId REQUIRED — see main mailx-store/db.ts: a (account, uid) write
     *  cross-wires body_path across every folder sharing the numeric UID. */
    updateBodyPath(accountId: string, folderId: number, uid: number, bodyPath: string): void;
    getMessagesWithoutBody(accountId: string, limit?: number): {
        uid: number;
        folderId: number;
    }[];
    getHighestUid(accountId: string, folderId: number): number;
    getOldestDate(accountId: string, folderId: number): number;
    getMessageCount(accountId: string, folderId: number): number;
    getUidsForFolder(accountId: string, folderId: number): number[];
    /** folderId REQUIRED. See main mailx-store/db.ts for why: IMAP UIDs are
     *  per-folder, so DELETE WHERE (account, uid) would wipe the same UID
     *  out of every folder. The pre-2026-05-27 implementation took only
     *  (accountId, uid) — that was the 70k-row data-loss bug. */
    deleteMessage(accountId: string, folderId: number, uid: number): void;
    recalcFolderCounts(folderId: number): void;
    beginTransaction(): void;
    commitTransaction(): void;
    rollbackTransaction(): void;
    /** Delete every contact row tied to a single Google contact identity
     *  (resourceName like "people/c12345"). Used by the People-API
     *  incremental sync when Google flags a contact as deleted. A single
     *  Google contact can have multiple email-rows; remove them all. */
    deleteContactByGoogleId(googleId: string): number;
    /** Stamp the google_id + organization on an already-recorded contact row.
     *  Web side mirrors mailx-store/db.ts — the Google sync calls
     *  `recordSentAddress` first to upsert, then this to attach the
     *  Google identity for incremental delete tracking. */
    setContactGoogleId(email: string, googleId: string, organization: string): void;
    recordSentAddress(name: string, email: string): void;
    seedContactsFromMessages(): number;
    /** Emails the user denylisted (contacts.jsonc#denylist). Filtered out of
     *  autocomplete. Populated by web-service's loadContactsConfig. */
    private _denylist;
    setContactsDenylist(emails: string[]): void;
    /** Regex patterns from contacts.jsonc#denylistPatterns — same semantics
     *  as desktop (mailx-store db.ts setContactsDenyPatterns): compiled
     *  case-insensitive, tested against the lowercased address, invalid
     *  patterns skipped with a warning. */
    private _denyPatterns;
    setContactsDenyPatterns(patterns: string[]): void;
    private isDenylisted;
    searchContacts(query: string, limit?: number): {
        name: string;
        email: string;
        source: string;
        useCount: number;
    }[];
    /** Address-book listing. Same shape as mailx-store/db.ts:listContacts so
     *  the address-book modal renders identically on desktop and Android. */
    listContacts(query: string, page?: number, pageSize?: number): {
        items: any[];
        total: number;
        page: number;
        pageSize: number;
    };
    upsertContact(name: string, email: string): void;
    deleteContactLocal(email: string): void;
    /** Q49 heuristic: has the user ever sent to `recipientEmail` with a
     *  non-empty Cc? Scans Sent folder(s). Used by compose to auto-expand
     *  the Cc row on reply to a frequent-Cc'd recipient. */
    hasCcHistoryTo(recipientEmail: string): boolean;
    searchMessages(query: string, page?: number, pageSize?: number, accountId?: string, folderId?: number): PagedResult<MessageEnvelope>;
    queueSyncAction(accountId: string, action: string, uid: number, folderId: number, extra?: {
        targetFolderId?: number;
        flags?: string[];
        rawMessage?: string;
    }): void;
    getPendingSyncActions(accountId: string): any[];
    completeSyncAction(id: number): void;
    failSyncAction(id: number, error: string): void;
    /** Delete a queued sync action by (accountId, action, uid) — used by the
     *  send path which tracks queued sends via a unique negative uid rather
     *  than threading the row id through the async send pipeline. */
    completeSyncActionByUid(accountId: string, action: string, uid: number): void;
    /** Mark a send-queue action failed by uid — same tracking-key rationale. */
    failSyncActionByUid(accountId: string, action: string, uid: number, error: string): void;
    getPendingSyncCount(accountId: string): number;
    getTotalPendingSyncCount(): number;
    /** Reset the entire database */
    resetStore(): Promise<void>;
    private rowToEnvelope;
}
//# sourceMappingURL=db.d.ts.map