/**
 * File-per-message body storage backend.
 *
 * Disk layout: {basePath}/{accountId}/<xx>/<uuid>.eml
 * Filename is an opaque UUID. Two-char prefix dir for filesystem fan-out.
 *
 * CRITICAL: the on-disk filename carries NO semantic meaning — not folder
 * id, not UID, not Message-ID. A new UUID is minted on every `putMessage`.
 * Moves, UID renumbers, UIDVALIDITY bumps cannot shadow a body because no
 * filename is ever reused. DB's `body_path` column is the sole authority
 * on where a given message's body lives.
 */
import type { MessageStore } from "@bobfrankston/mailx-types";
export declare class FileMessageStore implements MessageStore {
    private basePath;
    constructor(basePath: string);
    /** Fresh opaque path per call, returned RELATIVE to `basePath`. The DB
     *  stores this relative form so the body store can be relocated (or
     *  the user folder renamed — e.g. `.mailx → .rmfmail`) without the
     *  body_path entries breaking. */
    private newRelativePath;
    /** Resolve a stored path. Accepts either a relative path (post-2026-05
     *  format) or an absolute path (legacy entries until next-launch
     *  migration rewrites them). Either way, refuse anything outside the
     *  store as a directory-traversal guard. */
    private resolveStored;
    /** Write a new body. Returns a path RELATIVE to basePath; caller stores
     *  it in `body_path`. The (folderId, uid) args are kept for interface
     *  compatibility; they do NOT affect the filename.
     *
     *  Defensive content check: if the FIRST line of the would-be .eml
     *  matches an IMAP client-command pattern (`<tag> <UPPERCASE_CMD> ...`),
     *  the upstream IMAP parser desynced and wrote one of mailx's own
     *  outbound commands into the response stream — see the
     *  a39a84e1853441bcac09e1b3e1463e8d.eml corruption (2026-05-23). Refuse
     *  the write rather than persist garbage that the message-viewer will
     *  later render as broken. The caller's exception path treats this the
     *  same as any other transient fetch error; the reconciler re-enqueues. */
    putMessage(accountId: string, _folderId: number, _uid: number, raw: Buffer): Promise<string>;
    /** Resolve a stored body_path (relative or absolute) to an absolute
     *  filesystem path. Returns "" if the input doesn't resolve to a file
     *  inside the store. UI / "Source" actions need the absolute path so
     *  they can open / pass it to OS file pickers without re-introducing
     *  the basePath context every time. */
    absolutePath(stored: string): string;
    /** Read by stored path (relative or absolute). */
    readByPath(stored: string): Promise<Buffer>;
    hasByPath(stored: string): Promise<boolean>;
    unlinkByPath(stored: string): Promise<void>;
    /** One-shot migration: rewrite absolute body_path values that point at
     *  this store's basePath into relative form. Called once from db.ts on
     *  startup (gated by a kv flag); silently skipped after first run.
     *  Returns the count of rewritten paths.
     *
     *  Bodies whose absolute path is OUTSIDE basePath (the legacy
     *  `~/.mailx/mailxstore/...` entries on a machine where basePath is
     *  now `~/.rmfmail/mailxstore`) are left alone — the migration in
     *  mailx-settings already moves the files; this rewrite is purely
     *  about getting body_path to a relative shape. */
    rewriteAbsoluteToRelative(rows: Array<{
        id: number;
        body_path: string;
    }>, update: (id: number, newPath: string) => void): number;
    getMessagePath(_accountId: string, _folderId: number, _uid: number): string;
    getMessage(_accountId: string, _folderId: number, _uid: number): Promise<Buffer>;
    hasMessage(_accountId: string, _folderId: number, _uid: number): Promise<boolean>;
    deleteMessage(_accountId: string, _folderId: number, _uid: number): Promise<void>;
}
//# sourceMappingURL=file-store.d.ts.map