import type { RawFetchResult } from '../types.js';
export interface CachedFetchHeaders {
    etag?: string;
    lastModified?: string;
    fetchedAt: string;
}
/**
 * Look up cached ETag + Last-Modified for a URL. Returns null when no row
 * exists (first crawl, or table missing).
 */
export declare function getCachedHeaders(url: string): CachedFetchHeaders | null;
/**
 * Persist ETag + Last-Modified from a fresh fetch. Headers are looked up
 * case-insensitively so both `ETag` and `etag` are accepted.
 */
export declare function saveFetchHeaders(url: string, headers: Record<string, string>): void;
/**
 * Update only fetched_at on the existing row (no header change).
 */
export declare function markFetchedNotModified(url: string): void;
export interface ConditionalFetchOptions {
    conditionalHeaders?: {
        ifNoneMatch?: string;
        ifModifiedSince?: string;
    };
}
/**
 * Conditional-fetch wrapper. The wrapped `rawFetchFn` accepts an options
 * object so this layer can inject `If-None-Match` / `If-Modified-Since` from
 * the cached crawl_etags row. When the server replies 304 the network
 * payload is empty and the caller gets `notModified: true` for free; when
 * the server returns 200 + the same ETag/Last-Modified (legacy fallback)
 * the wrapper still detects the no-change case.
 */
export declare function conditionalFetch(url: string, rawFetchFn: (url: string, opts?: ConditionalFetchOptions) => Promise<RawFetchResult>): Promise<RawFetchResult & {
    notModified?: boolean;
}>;
/**
 * Test helper: wipe the crawl_etags table. Safe to call when the DB is
 * uninitialised — it just no-ops.
 */
export declare function _clearEtagCacheForTest(): void;
//# sourceMappingURL=etag-incremental.d.ts.map