import type { BigIntStats, Stats } from 'fs'; import { type FileObjectIdentity } from './file-identity.js'; export type RaceSafeReadCheckpoint = 'pre-open' | 'post-open' | 'post-read'; export interface RaceSafeReadContext { realPath: string; identity: FileObjectIdentity; } export type RaceSafeReadFailureReason = 'not-regular-file' | 'too-large' | 'changed'; export declare class RaceSafeReadError extends Error { readonly reason: RaceSafeReadFailureReason; constructor(reason: RaceSafeReadFailureReason, message: string, options?: { cause?: unknown; }); } export interface RaceSafeReadOptions { /** Use BigIntStats precision (dev/ino/size/mtimeNs/ctimeNs) end to end. */ bigint?: boolean; /** Prefixed into built-in error messages, e.g. `${label} changed while reading`. */ label?: string; /** Test-only synchronization points; behavior is passed through unchanged. */ hooks?: { afterOpen?: () => void | Promise; beforeFinalCheck?: () => void | Promise; }; /** * Called inside the same synchronization window as the built-in identity * checks at each checkpoint. A thrown error aborts the read exactly like an * identity mismatch. Use this to stack domain-specific checks (for example * Native directory-chain verification) without opening a second race window. */ verify?: (checkpoint: RaceSafeReadCheckpoint, context: RaceSafeReadContext) => void | Promise; } export interface RaceSafeReadResult { bytes: Buffer; stat: Stats | BigIntStats; realPath: string; } /** * Read a regular file through one descriptor with identity re-verification * before open, after open, and after the bounded read, so a path swapped for * a symlink or replacement file between checks is always rejected. * * ENOENT (and every other system error except ELOOP) propagates unchanged so * callers can keep their own missing-file semantics. */ export declare function readFileRaceSafe(file: string, maxBytes: number, options?: RaceSafeReadOptions): Promise; //# sourceMappingURL=race-safe-read.d.ts.map