* Start watching for file changes and auto-syncing. * * Uses native OS file events (FSEvents on macOS, inotify on Linux 19+, * ReadDirectoryChangesW on Windows) with debouncing to avoid thrashing. * * @param options - Watch options (debounce delay, callbacks) * @returns true if wat
(options: WatchOptions = {})
| 986 | * @returns true if watching started successfully |
| 987 | */ |
| 988 | watch(options: WatchOptions = {}): boolean { |
| 989 | if (this.watcher?.isActive()) return true; |
| 990 | |
| 991 | this.watcher = new FileWatcher( |
| 992 | this.projectRoot, |
| 993 | async (paths?: string[]) => { |
| 994 | const result = await this.sync({ paths }); |
| 995 | // sync() returns this exact zero-shape iff it failed to acquire the |
| 996 | // file lock (a real empty sync always has filesChecked > 0 because |
| 997 | // scanDirectory ran). Surface that to the watcher as a typed error |
| 998 | // so it keeps pendingFiles + reschedules instead of clearing them |
| 999 | // (#449). |
| 1000 | if (result.filesChecked === 0 && result.durationMs === 0) { |
| 1001 | throw new LockUnavailableError(); |
| 1002 | } |
| 1003 | const filesChanged = result.filesAdded + result.filesModified + result.filesRemoved; |
| 1004 | return { filesChanged, durationMs: result.durationMs }; |
| 1005 | }, |
| 1006 | options |
| 1007 | ); |
| 1008 | |
| 1009 | return this.watcher.start(); |
| 1010 | } |
| 1011 | |
| 1012 | /** |
| 1013 | * Stop watching for file changes. |