import type { HttpMethod, MisinaContext, MisinaPlugin } from "../types.mjs"; export interface CacheEntry { response: Response; expires: number; etag?: string; lastModified?: string; /** Header values that contributed to the cache key, per Vary. */ vary?: Record; /** * RFC 5861 stale-while-revalidate window in milliseconds. While in this * window the entry is served stale and revalidated in the background. */ staleWhileRevalidate?: number; /** * RFC 5861 stale-if-error window in milliseconds. When the origin * fails (5xx, network error) within this window the cached entry is * served instead of the failure. */ staleIfError?: number; /** RFC 8246 — entry is guaranteed fresh until `expires`, no revalidation. */ immutable?: boolean; } export interface ParsedCacheControl { maxAge?: number; sMaxAge?: number; noStore?: boolean; noCache?: boolean; immutable?: boolean; public?: boolean; private?: boolean; staleWhileRevalidate?: number; staleIfError?: number; } /** * Parse a `Cache-Control` header value (RFC 9111, RFC 5861, RFC 8246). * Unknown directives are ignored. Tolerant of whitespace and case. */ export declare function parseCacheControl(header: string | null | undefined): ParsedCacheControl; /** * RFC 9211 Cache-Status header. Each list member identifies a cache by * token (or string) and carries parameters like `hit`, `fwd=miss`, * `ttl=NNN`, etc. */ export interface CacheStatusEntry { /** Cache identifier (token or quoted string). */ cache: string; hit?: boolean; fwd?: string; fwdStatus?: number; ttl?: number; stored?: boolean; collapsed?: boolean; key?: string; detail?: string; /** Any unknown parameters preserved as-is. */ params: Record; } /** * Parse a `Cache-Status` header (RFC 9211) into ordered entries — first * entry is the cache nearest to the origin, last is the cache nearest to * the user (per RFC 9211 §2). Returns an empty array on parse failure. */ export declare function parseCacheStatus(header: string | null | undefined): CacheStatusEntry[]; export interface CacheStore { get: (key: string) => CacheEntry | undefined | Promise; set: (key: string, entry: CacheEntry) => void | Promise; delete: (key: string) => void | Promise; clear?: () => void | Promise; } export interface CacheOptions { store?: CacheStore; /** Time-to-live in milliseconds. Default: 60_000. */ ttl?: number; /** Methods eligible for caching. Default: GET only. */ methods?: HttpMethod[]; /** Compute the cache key. Default: `${method} ${url}`. */ key?: (ctx: MisinaContext) => string; /** Send `If-None-Match`/`If-Modified-Since` for stale entries. Default: true. */ revalidate?: boolean; /** * Honor `Cache-Control: max-age=N` from responses, overriding the local * `ttl` option for that entry. Default: true. */ honorCacheControl?: boolean; /** * Decide whether to cache a given response. Receives the request and the * response that's about to be cached; return `false` to skip storing. * Useful to filter out 5xx, error envelopes, or sensitive paths. */ shouldStore?: (request: Request, response: Response) => boolean; /** * Mutate a cache entry before it's stored. Receives the entry; return a * replacement or `undefined` to abandon caching this entry. Use to scrub * secrets, denormalize, or attach metadata. */ beforeStore?: (entry: CacheEntry) => CacheEntry | undefined | Promise; } /** In-memory LRU-ish cache (no eviction by default — pair with `max`). */ export declare function memoryStore(opts?: { max?: number; }): CacheStore; /** * Wrap a Misina with a response cache. Caches by `${method} ${url}` plus * any headers listed in the response's `Vary` (RFC 9111 §4.1). Honors * `Cache-Control: no-store` (skip cache), `Cache-Control: max-age=N` * (override TTL), and ETag / Last-Modified for revalidation. */ export declare function cache(opts?: CacheOptions): MisinaPlugin;