/** * The in-process grep engine: one search implementation shared by the main * thread and a small pool of worker threads. * * Why workers: on a warm page cache, a scan is per-file syscall and callback * overhead, and every async `fs` call funnels through the main thread's event * loop. Workers reading synchronously in parallel halve the scan time and keep * the daemon's event loop free while they do it. Measured on macOS, four * workers beat both fewer and more (more contend on file-open locks). * * The three functions marked SELF-CONTAINED are serialized into the worker * with `Function.prototype.toString`, so the worker runs the exact code the * main thread runs. They may reference only their parameters and globals — * no imports, no module constants. The sidecar is one bundled file, so the * worker is built from source text rather than loaded from a separate module. */ import type fs from "node:fs"; export interface ScanTextOptions { source: string; flags: string; /** Reject a file with one regex pass over its whole text first (unsafe with lookaround). */ prefilter: boolean; maxResults: number; /** Epoch ms after which the scan stops. */ expiresAt: number; maxLineLength: number; /** Check the clock every N lines. */ checkInterval: number; /** Lines checked for a NUL byte before the file is treated as binary. */ sniffLines: number; } export interface ScanTextResult { lines: string[]; /** The deadline passed mid-file; `lines` holds what was found before it. */ expired: boolean; } /** * SELF-CONTAINED. Search in-memory file text with the streaming scanner's * semantics: same lines, same line numbers, same matches, same truncation. */ export declare function scanText(input: string, relPath: string, o: ScanTextOptions): ScanTextResult; /** Cheap "could this file match at all?" check on undecoded bytes. */ export type ByteFilter = (bytes: Buffer) => boolean; /** * SELF-CONTAINED. A filter passing only bytes that contain one of `literals`. * * Literals are ASCII only (see `requiredLiterals`): ASCII bytes never occur * inside a multi-byte UTF-8 sequence or its replacement, so "the bytes contain * it" and "the decoded text contains it" agree. For case-insensitive search * the bytes are viewed as latin1 (a near-free copy): non-Unicode JS case * folding never maps a non-ASCII character onto ASCII, so the same holds. */ export declare function makeByteFilter(literals: readonly string[] | undefined, caseInsensitive: boolean): ByteFilter | undefined; /** * SELF-CONTAINED. Synchronously read a regular file of at most `limit` bytes * into `scratch`, refusing symlinks like `readFileBounded`. The returned view * aliases `scratch`: use it before the next call. `undefined` means "not * readable this way" and sends the file to the main thread's slower path. */ export declare function readSmallFileSync(fsModule: typeof fs, filePath: string, limit: number, scratch: Buffer): Buffer | undefined; /** One file to scan: absolute path for reading, display path for output. */ export type ScanTarget = readonly [absolutePath: string, relativePath: string]; export interface ScanJob { files: readonly ScanTarget[]; options: ScanTextOptions; literals: readonly string[] | undefined; caseInsensitive: boolean; /** Largest file read whole; larger files come back as `null`. */ readLimit: number; /** Stop the chunk once this many lines are found (see `scanWithWorkers`). */ stopAfter: number; } export interface ScanJobResult { /** Per file, in order: matched lines, or `null` for "scan on the main thread". */ results: Array; expired: boolean; } export declare class GrepWorkerPool { private readonly idle; private readonly waiters; private readonly all; private idleTimer; private disposed; constructor(size: number, readLimit: number); get size(): number; get isDisposed(): boolean; /** Run one job; rejects if the pool is or becomes unusable. */ run(job: ScanJob): Promise; dispose(): void; private acquire; private release; private armIdleTimer; } export declare function getGrepWorkerPool(readLimit: number): GrepWorkerPool | undefined; /** Test seam: stop the shared pool's workers. */ export declare function disposeGrepWorkerPool(): void;