import { Import } from '@rushstack/node-core-library' ; import anymatch from 'anymatch' ; import { ICommandConfig } from '../../type' ; import { MultitasksLogger } from '../../log/multi-tasks-log' ; import { DagOperator } from '../../dag/operator' ; import { IProjectNode } from '../../projects/get-projects' ; import { Argu } from '../../utils/types' ; import { WatchedProjectsState } from './watch-projects-state' ; import { defaultBuildWatchCmds , BuildWatchCmdsType } from './cmds' ; import { createDependenciesTask , createDevTask } from './create-task' ; const chokidar = Import . lazy ( 'chokidar' , require ) ; export interface IBuildWatchConfig extends ICommandConfig { onlySelf ? : boolean ; ignoreMaybeChanged ? : Argu < typeof anymatch > ; needInit ? : boolean ; } export interface IProjectChangeResult { /**
     * The set of projects that have changed since the last iteration
     */ changedProjects : Readonly < IProjectNode [ ] > ; /**
     * Contains the git hashes for all tracked files in the repo
     */ state : any ; } const getIgnored = ( config ) => ( watchFilePath ) => { const nodeModulesPattern = /(?:^|[\\/])node_modules/g ; if ( nodeModulesPattern . test ( watchFilePath ) || watchFilePath . includes ( 'dist' ) ) { return true ; } if ( config . ignoreMaybeChanged ) { return anymatch ( config . ignoreMaybeChanged ) ( watchFilePath ) ; } return false ; } ; export const runBuildWatchTask = async ( projectName , operator , config , taskCmds = defaultBuildWatchCmds ) => { const { needInit = true } = config ; const taskLogger = new MultitasksLogger ( ) ; const dependenciesTask = createDependenciesTask ( config , taskCmds , taskLogger ) ; const devTask = createDevTask ( config , taskCmds , taskLogger ) ; const fromNodes = operator . getNodeAllDependencyData ( projectName ) ; const watchedProjectState = new WatchedProjectsState ( fromNodes , config ) ; const watcher = new chokidar . FSWatcher ( { persistent : true , cwd : config . rootPath , followSymlinks : false , ignoreInitial : true , ignored : getIgnored ( config ) , disableGlobbing : true , interval : 1000 , } ) ; watcher . add ( watchedProjectState . getWatchedProjectsPath ( ) ) ; if ( needInit ) { await operator . traverseDependenciesToProject ( projectName , async ( currentProject ) => { await dependenciesTask ( currentProject ) ; } ) ; } await new Promise ( resolve => { console . info ( 'start watch' ) ; watcher . on ( 'all' , async ( eventName , changeFilePath ) => { if ( eventName === 'add' ) { watchedProjectState . updateState ( ) ; } const changedProject = watchedProjectState . getChangedProject ( changeFilePath ) ; if ( changedProject ) { await operator . traverseProjectToDependent ( changedProject . name , async ( currentProject , _ , earlyFinish ) => { if ( currentProject . name === projectName ) { earlyFinish ( ) ; return ; } if ( watchedProjectState . watchProjectsName . includes ( currentProject . name ) ) { console . info ( 'run build' , currentProject . name ) ; await dependenciesTask ( currentProject ) ; } } , { withSelf : true } ) ; resolve ( null ) ; } else { console . info ( 'changed is not in monorepo manager' ) ; } } ) ; resolve ( null ) ; } ) ; await devTask ( operator . getNodeData ( projectName , { checkExist : true } ) ) ; } ;