import type { Entry } from '../entry/entry.js';
import type { RollupBucket, RollupDelta, RollupStore } from '../rollup/rollup-store.js';
import type { BoundedPruneCapable, BoundedPruneResult, BoundedPruneScope, EntryQuery, EntryWithBatch, LeaseCapableStorage, Page, PruneScope, TagCount, TagQuery } from './storage-provider.js';
export interface SqliteStorageOptions {
    /** File path or ':memory:'. Defaults to ':memory:'. */
    path?: string;
}
/**
 * Default storage provider: embedded SQLite via better-sqlite3, JSON1 for tags.
 *
 * Declared against {@link BoundedPruneCapable} and {@link LeaseCapableStorage}
 * (both extend `StorageProvider`) so dropping either capability is a compile
 * error rather than a silent fall back to unbounded, unlocked pruning.
 */
export declare class SqliteStorageProvider implements BoundedPruneCapable, LeaseCapableStorage, RollupStore {
    private readonly db;
    /** Prepared once; reused by store() and update(). */
    private readonly stmtInsert;
    /** Prepared once; reused by find() and update(). */
    private readonly stmtFindRow;
    /** Prepared once; reused by batch(). */
    private readonly stmtBatch;
    /** Prepared once; reused by recordRollups() to read the existing rollup row. */
    private readonly stmtSelectRollup;
    /** Prepared once; reused by recordRollups() — additive upsert incl. histogram. */
    private readonly stmtUpsertRollup;
    constructor(options?: SqliteStorageOptions);
    close(): void;
    /**
     * Idempotently adds a column to `table`. SQLite has no
     * `add column if not exists`, so we attempt the alter and swallow ONLY the
     * duplicate-column error (the column is already present); anything else re-throws.
     */
    private ensureColumn;
    store(entries: Entry[]): Promise<void>;
    update(id: string, patch: Partial<Entry>): Promise<void>;
    find(id: string): Promise<EntryWithBatch | null>;
    get(query: EntryQuery): Promise<Page<Entry>>;
    /**
     * Returns all entries belonging to `batchId`, sorted by sequence ascending.
     * Capped at 1000 rows to avoid pathological memory loads.
     */
    batch(batchId: string): Promise<Entry[]>;
    tags(prefix?: string, query?: TagQuery): Promise<TagCount[]>;
    prune(olderThan: Date, keepLast?: number): Promise<number>;
    pruneScoped(input: PruneScope): Promise<number>;
    pruneScopedBatch(input: BoundedPruneScope): Promise<BoundedPruneResult>;
    tryAcquireLease(key: string, owner: string, ttlMs: number, nowMs: number): Promise<boolean>;
    releaseLease(key: string, owner: string): Promise<void>;
    /**
     * Returns the SQL fragment + ordered params for a {@link PruneScope}'s type
     * selector. `type` → `type = ?`; `excludeTypes` → `type not in (?, …)` (an
     * empty exclude list degenerates to "no type filter", i.e. all types); neither
     * → no fragment.
     */
    private scopedTypePredicate;
    clear(): Promise<void>;
    /**
     * SHARED new-exception dedup. Atomic check-and-update INSIDE a transaction so
     * concurrent replicas writing to the SAME database file race safely: exactly
     * one sees `true` for a brand-new family. Returns `true` when the family was
     * never seen or last seen longer ago than `windowMs`.
     */
    markFamilySeen(familyHash: string, nowMs: number, windowMs: number): Promise<boolean>;
    recordRollups(deltas: RollupDelta[]): Promise<void>;
    queryRollups(metrics: string[], fromBucket: number, toBucket: number): Promise<RollupBucket[]>;
    /**
     * Parses a stored histogram JSON string back into a number[]. Legacy/null rows
     * and any malformed JSON yield null, which {@link normalizeHistogram} turns
     * into an all-zeros array of the canonical length.
     */
    private parseHistogram;
    private toRow;
    private fromRow;
}
//# sourceMappingURL=sqlite-storage-provider.d.ts.map