import type { DocPage, SearchHit } from './types.js';
/** Per-page overrides supplied by the host, e.g. from a build manifest. */
export interface PageMetadata {
    title?: string;
    description?: string;
    url?: string;
}
export interface DocStoreOptions {
    /** Directory holding the markdown docs. */
    root: string;
    /** Resolve extra metadata for a page path (root-relative, no extension). Wins over frontmatter and `baseUrl`. */
    metadata?: (docPath: string) => PageMetadata | undefined;
    /** Public site root used to build `url` fields, e.g. `https://docs.example.com`. */
    baseUrl?: string;
    extensions?: string[];
    /** Directory names to skip while walking. */
    ignore?: string[];
}
export interface SearchOptions {
    limit?: number;
    pathPrefix?: string;
    /** Max hits from the same page (default 3), so one long page does not crowd out the rest. */
    perPage?: number;
}
export interface StoreStats {
    root: string;
    pages: number;
    sections: number;
    words: number;
    indexedAt: Date | null;
}
/**
 * Tokenizer that keeps identifiers such as `search_docs`, `rate-limit` or
 * `foo.bar` as one token and also emits their parts, so an exact identifier
 * query outranks pages that merely contain the words.
 */
export declare const tokenize: (text: string) => string[];
/** Turn any user-supplied reference into the canonical page path. */
export declare const normalizePath: (ref: string) => string;
/** URL for a section: page URL plus anchor, unless the page URL already carries a fragment (e.g. a Redoc deep link). */
export declare const sectionUrl: (page: Pick<DocPage, "url">, anchor: string) => string | undefined;
export declare class DocStore {
    readonly root: string;
    readonly baseUrl: string | undefined;
    private readonly metadata;
    private readonly extensions;
    private readonly ignore;
    private pagesByPath;
    private pagesByUrl;
    private index;
    private indexedAt;
    private loading;
    constructor(opts: DocStoreOptions);
    /** Read every page under `root` and rebuild the search index. Safe to call repeatedly. */
    load(): Promise<void>;
    private rebuild;
    private walk;
    private readPage;
    private urlFor;
    private ensureLoaded;
    stats(): StoreStats;
    listPages(pathPrefix?: string): DocPage[];
    /** Resolve a page by path, tolerating extensions, leading `./`, `docs://`, anchors and folder-index shorthand. */
    get(ref: string): DocPage | undefined;
    /**
     * Resolve a page by its public URL (as configured via `baseUrl` or the
     * `metadata` hook), tolerating a trailing slash and a `#fragment`. Returns
     * the page plus the fragment as a candidate section anchor, when the URL's
     * own fragment isn't already baked into the page's stored URL (e.g. a
     * Redoc deep link) — matching that case would strip a fragment the page
     * actually needs.
     */
    getByUrl(url: string): {
        page: DocPage;
        anchor?: string;
    } | undefined;
    /** Resolve a relative link from `fromPath` to a page in the store. */
    resolveLink(fromPath: string, href: string): DocPage | undefined;
    search(query: string, opts?: SearchOptions): SearchHit[];
    /**
     * Rebuild the index whenever a file under `root` changes. Returns a function
     * that stops watching. Recursive watching needs Node 20+ on Linux; on older
     * setups this logs a warning and returns a no-op.
     */
    watch(onReload?: (err: Error | null) => void, debounceMs?: number): () => void;
}
//# sourceMappingURL=store.d.ts.map