import type { FileStat } from '../../types.ts';
import { type Clock } from '../../utils/clock.ts';
import type { Evicted, IndexSnapshot, ListResult, LookupResult, SetDirOptions } from './config.ts';
export declare abstract class IndexCacheStore {
    /** The clock every listing deadline of this store is set and read on. */
    readonly clock: Clock;
    /** @param clock the clock listings expire on; undefined means the real one. */
    constructor(clock?: Clock);
    /** Seconds a listing lives when its writer names no expiry. */
    abstract readonly ttl: number;
    /**
     * Merge snapshots by path; deferred stores flush before operations or
     * close. Clear discards them. `version` replaces the version of every
     * listed folder, and null clears it.
     */
    abstract seed(entries: ReadonlyMap<string, FileStat>, children: ReadonlyMap<string, readonly string[]>, expiresAt: Date, version?: string | null): void;
    /** Apply this index's ownership rules to a refill snapshot. */
    scopeSnapshot(snapshot: IndexSnapshot): IndexSnapshot;
    abstract entries(): Promise<Map<string, FileStat>>;
    abstract get(vfsPath: string): Promise<LookupResult>;
    /** Read retained rows by path, omitting missing entries. */
    getMany(vfsPaths: readonly string[]): Promise<Map<string, FileStat>>;
    abstract put(vfsPath: string, entry: FileStat): Promise<void>;
    /**
     * Keep a row a create just made, named in its parent's listing. A listing
     * held for the parent gains the name, in order, and stays what it was: a
     * complete one stays complete, since the create is the only change to it.
     * Replacing a directory with a file leaves the parent partial so a
     * coexisting prefix can be listed again.
     * With none held, the parent gets a partial listing that names the one
     * entry, which proves it without proving anything absent; `expiredAt` is
     * the latest that listing may live, null for the store's own lifetime.
     */
    abstract addEntry(vfsPath: string, entry: FileStat, expiredAt?: Date | null): Promise<void>;
    /** Atomically replace an existing row without renewing its listing; custom stores may decline. */
    replaceIfUnchanged(_path: string, _predecessor: string, _entry: FileStat): Promise<boolean>;
    /**
     * A directory's listing. Given `child`, the one key a lookup asks about,
     * its entries are narrowed to that key, kept where the listing names it,
     * so a stat of each child of a large directory costs no scan or copy of
     * the whole listing, which made `ls` of one quadratic
     * (strukto-ai/mirage#1840). A custom store may answer the whole listing
     * instead: callers check the key against the entries either way.
     */
    abstract listDir(vfsPath: string, child?: string): Promise<ListResult>;
    /**
     * Cache a complete directory listing. A complete listing names every
     * child, so a child the previous listing named and this one does not is
     * gone: its row goes, and a gone directory takes its listing and every
     * row beneath it. Rows only `put` wrote were never named, so they stay. A
     * window evicts nothing. Resolves to the children that went.
     */
    abstract setDir(vfsPath: string, entries: readonly [string, FileStat][], expiredAt?: Date | null, options?: SetDirOptions): Promise<Evicted[]>;
    /**
     * Hand children a re-list found gone to the mount's cleanup. A raw store
     * belongs to no mount, so there is nothing to clean.
     */
    reportGone(_gone: readonly Evicted[]): Promise<void>;
    /** Token captured before fetching listings, including descendant seeds. */
    refillToken(): Promise<string>;
    /** Expire complete parent listings contradicted by the observed immediate child keys. */
    invalidateMissing(_paths: readonly string[]): Promise<boolean>;
    /** null rejects an older refill without reporting any deletions. */
    refillDir(_path: string, _entries: readonly [string, FileStat][], _token: string, _expiredAt?: Date | null, _options?: SetDirOptions & {
        partial?: boolean;
    }): Promise<Evicted[] | null>;
    /**
     * Drop a changed row and demote its parent listing to partial.
     * Retain siblings, the original deadline and deletion history. Clear the
     * parent's version and window without recording a new observation.
     * Missing or stale membership must never become fresh.
     */
    abstract invalidateEntry(vfsPath: string): Promise<void>;
    abstract invalidateDir(vfsPath: string): Promise<void>;
    /**
     * Cache observed children without claiming a complete directory. Stores
     * supporting partial freshness return these keys as `partialEntries`
     * until expiry or invalidation. A partial listing proves nothing
     * complete, so it carries no version. Custom stores inherit the conservative
     * put-only fallback, which refreshes the parent on the next lookup.
     */
    setPartialDir(vfsPath: string, entries: readonly [string, FileStat][], _expiredAt?: Date | null): Promise<void>;
    /**
     * Drop `vfsPath` and everything cached below it.
     *
     * `invalidateDir` drops one directory's listing and its direct children's
     * entries, which is enough for a mutation that named a path. A push
     * notification that can only name a scope needs the whole subtree gone,
     * because the listings further down were cached independently and nothing
     * above them expires them.
     *
     * `remember` retains current membership as deletion history for the next
     * complete listing; the default forgets it.
     * Mirrors Python `IndexCacheStore.invalidate_prefix`.
     */
    abstract invalidatePrefix(vfsPath: string, excluded?: readonly string[], remember?: boolean): Promise<void>;
    /**
     * Whether the running command fetched `folder`'s listing itself.
     *
     * A raw store belongs to no mount and no command, so it cannot tell and
     * answers false; a mount's view answers from its cache manager. Mirrors
     * Python's `listed_this_command`.
     */
    listedThisCommand(_folder: string): boolean;
    /**
     * Whether a listing is cached at `vfsPath` or anywhere under it.
     *
     * Asked when a removed path may be a folder, to avoid a subtree scan for
     * each plain-file delete. Only a retained listing counts, even one past its
     * ttl (expiry is checked when it is read). A row or tombstone does not prove
     * a listing remains below the path. A children-first delete stream may
     * already have removed every listing before the folder's own event arrives.
     *
     * A store that cannot tell answers true, so callers conservatively drop
     * the subtree and refetch it.
     *
     * Mirrors Python `IndexCacheStore.holds_subtree`.
     */
    holdsSubtree(_vfsPath: string): Promise<boolean>;
    /**
     * Mark every entry stale without discarding it.
     *
     * The difference from `clear` is what a later lookup can tell. `clear`
     * leaves an empty store, which reads exactly like a store that was never
     * filled, so a backend whose index *is* its listing cannot tell an
     * invalidation from an empty repository. Expiring instead keeps that
     * distinction: the lookup answers EXPIRED and the backend refetches.
     */
    abstract invalidate(): Promise<void>;
    abstract clear(): Promise<void>;
    /**
     * Release whatever the store holds open. The default is a no-op:
     * an in-memory index owns nothing. A store backed by a connection
     * (redis) overrides this and must be idempotent — `close()` is
     * called once per owning VFS, and a VFS shared between
     * workspaces is closed by whichever one owns it.
     *
     * Mirrors Python `IndexCacheStore.close` (`cache/index/store.py`).
     */
    close(): Promise<void>;
}
//# sourceMappingURL=store.d.ts.map