/** * 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; /** 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; 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; getUnifiedInbox(page?: number, pageSize?: number): PagedResult; 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, card?: Partial>): 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; 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; private rowToEnvelope; } //# sourceMappingURL=db.d.ts.map