Your music, beautifully tracked. All yours. (coming soon) teal.fm
teal-fm atproto
at main 61 lines 1.8 kB view raw
1import chokidar from 'chokidar'; 2import { join } from 'path'; 3import pc from 'picocolors'; 4import { generate } from './generate.js'; 5import { findWorkspaceRoot } from '../utils/workspace.js'; 6 7interface WatchOptions { 8 tsOnly?: boolean; 9 rustOnly?: boolean; 10} 11 12export async function watch(options: WatchOptions = {}) { 13 const workspaceRoot = findWorkspaceRoot(); 14 const lexiconsPath = join(workspaceRoot, 'lexicons'); 15 16 console.log(pc.blue('👀 Watching lexicon files for changes...')); 17 console.log(pc.gray(` Lexicons directory: ${lexiconsPath}`)); 18 console.log(pc.yellow(' Press Ctrl+C to stop watching')); 19 20 const watcher = chokidar.watch(lexiconsPath, { 21 ignored: /(^|[\/\\])\../, // ignore dotfiles 22 persistent: true, 23 ignoreInitial: true 24 }); 25 26 let isGenerating = false; 27 28 const handleChange = async (path: string, event: string) => { 29 if (isGenerating) { 30 console.log(pc.yellow(` ⏳ Skipping ${event} for ${path} (generation in progress)`)); 31 return; 32 } 33 34 console.log(pc.cyan(` 📝 ${event}: ${path}`)); 35 36 isGenerating = true; 37 try { 38 await generate(options); 39 } catch (error) { 40 console.error(pc.red(' ❌ Auto-generation failed:'), error instanceof Error ? error.message : String(error)); 41 } finally { 42 isGenerating = false; 43 } 44 }; 45 46 watcher 47 .on('add', (path) => handleChange(path, 'Added')) 48 .on('change', (path) => handleChange(path, 'Changed')) 49 .on('unlink', (path) => handleChange(path, 'Removed')) 50 .on('error', (error) => console.error(pc.red('Watcher error:'), error)); 51 52 // Handle graceful shutdown 53 process.on('SIGINT', () => { 54 console.log(pc.yellow('\n🛑 Stopping lexicon watcher...')); 55 watcher.close(); 56 process.exit(0); 57 }); 58 59 // Keep the process alive 60 return new Promise<void>(() => {}); 61}