Routes a file-system event to fsTree mutation and optional rebuild trigger.
unlinkDir bypasses the extension filter so deleted directories always clean up fsTree.
When a build is already in progress, queues the event as a pending trigger (last-write-wins).
Mutates fsTree in place based on a file-system event.
Reads a file, re-reading until two reads spaced STABILITY_GAP_MS apart return byte-identical
content — so a file caught mid-write (Windows truncate→flush; see STABILITY_GAP_MS) is hashed
only once its bytes have settled. Bounded by MAX_STABILITY_ATTEMPTS; returns the latest content
if it never stabilizes. read is injectable for tests; production reads from disk. Read errors
propagate so the caller's catch can treat a vanished file as a removal.
Scans watchPath recursively and fires add / change / unlink events for any delta
between the directory contents and config.fsTree. Used as a 1 s safety-net poll on macOS
where FSEvents can drop events under load — additions and removals are recovered from the
directory listing, and modifications are recovered by re-stat'ing every tracked file and
firing change whenever its mtime is newer than config.state.watch.lastBuildEndMs (the moment the
last build saw the file). The seed for that baseline is set in setup.
Starts fs.watch watchers for each lookup path and calls onEventFunc on JS/TS file changes,
debounced via a per-file timestamp. Also watches each path's parent directory to detect when a
watched directory is renamed or deleted (since fs.watch tracks by inode, not path).
Uses config.fsTree to distinguish unlink (tracked file) from unlinkDir (directory) on deletion.
Maps a lookup path to a path fs.watch can actually watch. A real file or directory is returned
as-is; a glob is walked up to the deepest ancestor directory that exists — its base dir — which
fs.watch can watch recursively (test/x/!(plugin).ts collapses to test/x).
The fs calls rescanDirectoryForDelta makes — injectable so a platform-specific
readdir/stat disagreement can be reproduced deterministically. Production uses the real fs.
-
readdir: readdir
Lists the directory tree. Its dirent types are unreliable on Windows — see
isMissing. -
stat: stat
Resolves a path (follows symlinks). Used to drop entries that are genuinely gone.
Usage
import * as mod from "lib/setup/file-watcher.ts";