44 lines
1.4 KiB
TypeScript
44 lines
1.4 KiB
TypeScript
import chokidar, { FSWatcher } from 'chokidar';
|
|
import path from 'path';
|
|
import { NOTEBOOK_ROOT } from '../config/paths.js';
|
|
import { eventBus } from '../events/eventBus.js';
|
|
import { logger } from '../utils/logger.js';
|
|
import { toPosixPath } from '../../shared/utils/path.js';
|
|
|
|
let watcher: FSWatcher | null = null;
|
|
|
|
export const startWatcher = (): void => {
|
|
if (watcher) return;
|
|
|
|
logger.info(`Starting file watcher for: ${NOTEBOOK_ROOT}`);
|
|
|
|
watcher = chokidar.watch(NOTEBOOK_ROOT, {
|
|
ignored: /(^|[\/\\])\../,
|
|
persistent: true,
|
|
ignoreInitial: true,
|
|
});
|
|
|
|
const broadcast = (event: string, changedPath: string) => {
|
|
const rel = path.relative(NOTEBOOK_ROOT, changedPath);
|
|
if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) return;
|
|
logger.info(`File event: ${event} - ${rel}`);
|
|
eventBus.broadcast({ event, path: toPosixPath(rel) });
|
|
};
|
|
|
|
watcher
|
|
.on('add', (p) => broadcast('add', p))
|
|
.on('change', (p) => broadcast('change', p))
|
|
.on('unlink', (p) => broadcast('unlink', p))
|
|
.on('addDir', (p) => broadcast('addDir', p))
|
|
.on('unlinkDir', (p) => broadcast('unlinkDir', p))
|
|
.on('ready', () => logger.info('File watcher ready'))
|
|
.on('error', (err) => logger.error('File watcher error:', err));
|
|
};
|
|
|
|
export const stopWatcher = async (): Promise<void> => {
|
|
if (watcher) {
|
|
await watcher.close();
|
|
watcher = null;
|
|
}
|
|
};
|