1import chalk from 'chalk'; 2import { watchFile } from 'fs'; 3import path from 'path'; 4import resolveFrom from 'resolve-from'; 5 6import * as Log from '../log'; 7import { memoize } from './fn'; 8 9const debug = require('debug')('expo:utils:fileNotifier') as typeof console.log; 10 11/** Observes and reports file changes. */ 12export class FileNotifier { 13 constructor( 14 /** Project root to resolve the module IDs relative to. */ 15 private projectRoot: string, 16 /** List of module IDs sorted by priority. Only the first file that exists will be observed. */ 17 private moduleIds: string[], 18 private settings: { 19 /** An additional warning message to add to the notice. */ 20 additionalWarning?: string; 21 } = {} 22 ) {} 23 24 /** Get the file in the project. */ 25 private resolveFilePath(): string | null { 26 for (const moduleId of this.moduleIds) { 27 const filePath = resolveFrom.silent(this.projectRoot, moduleId); 28 if (filePath) { 29 return filePath; 30 } 31 } 32 return null; 33 } 34 35 public startObserving() { 36 const configPath = this.resolveFilePath(); 37 if (configPath) { 38 debug(`Observing ${configPath}`); 39 return this.watchFile(configPath); 40 } 41 return configPath; 42 } 43 44 /** Watch the file and warn to reload the CLI if it changes. */ 45 public watchFile = memoize(this.startWatchingFile.bind(this)); 46 47 private startWatchingFile(filePath: string): string { 48 const configName = path.relative(this.projectRoot, filePath); 49 watchFile(filePath, (cur: any, prev: any) => { 50 if (prev.size || cur.size) { 51 Log.log( 52 `\u203A Detected a change in ${chalk.bold( 53 configName 54 )}. Restart the server to see the new results.` + (this.settings.additionalWarning || '') 55 ); 56 } 57 }); 58 return filePath; 59 } 60} 61