import type { Message } from "@slackwsh/contracts";
/**
 * The entity cache for messages (§5.3 "Local cache" / ADR-004's rejection of
 * TanStack Query as the primary store — this is deliberately *not* a
 * request cache). One instance per client; holds a bounded window per
 * channel, LRU-evicted at the channel level.
 *
 * Invariants owned here:
 *  - I1 (total order): `getMessages` always returns seq-ascending.
 *  - I3 (idempotency): `upsert` keyed by message `id` is a no-op replace,
 *    never a duplicate — the server is what enforces uniqueness on
 *    (channel_id, client_msg_id); this store just never renders the same
 *    id twice regardless of how many times it arrives.
 *  - I8 (mutation convergence): edits/deletes/reactions apply only if the
 *    incoming revision is >= what's cached, so out-of-order delivery of an
 *    edit followed by a stale re-delivery of the pre-edit state can't undo
 *    a newer edit.
 */
export declare class MessageStore {
    private readonly channels;
    private readonly channelOrder;
    private readonly messagesPerChannel;
    private readonly maxChannels;
    constructor(opts?: {
        messagesPerChannel?: number;
        maxChannels?: number;
    });
    upsert(channelId: string, message: Message): void;
    applyDelete(channelId: string, messageId: string | number, seq: number): void;
    /** Always seq-ascending (I1) — never sorted by arrival or wall-clock time. */
    getMessages(channelId: string): Message[];
    getMessage(channelId: string, messageId: string | number): Message | undefined;
    clearChannel(channelId: string): void;
    private touchChannel;
    /** Keeps only the most recent N messages by seq — "bounded window per
     * channel" (§5.3). Evicting by lowest seq is safe: catch-up (I7) always
     * re-fetches from the server's authoritative log, never from this cache
     * alone, so trimming old entries never fabricates a gap the client can't
     * recover from. */
    private trimToWindow;
}
//# sourceMappingURL=message-store.d.ts.map