UNPKG

@sprucelabs/spruce-cli

Version:

Command line interface for building Spruce skills.

112 lines (92 loc) 3.13 kB
import pathUtil from 'path' import { diskUtil } from '@sprucelabs/spruce-skill-utils' import chokidar from 'chokidar' import { GeneratedFile, GeneratedFileOrDir } from '../../types/cli.types' import AbstractFeature from '../AbstractFeature' import { FeatureCode } from '../features.types' export default class WatchFeature extends AbstractFeature { public description = 'Watches for changes on the file system and emits app level events for other features to respond to.' public code: FeatureCode = 'watch' public nameReadable = 'Watch' private _isWatching = false private watcher?: any private timeoutId?: NodeJS.Timeout private changesSinceLastChange: GeneratedFileOrDir[] = [] public async isWatching() { return this._isWatching } public async startWatching(options?: { delay?: number sourceDir?: string }) { this._isWatching = true const watchDir = diskUtil.resolvePath( this.cwd, options?.sourceDir ?? '' ) this.watcher = chokidar.watch( [ diskUtil.resolvePath(watchDir, 'build'), diskUtil.resolvePath(watchDir, 'dist'), ], { ignoreInitial: true, } ) this.watcher.on('all', async (action: ChokidarAction, path: string) => { this.changesSinceLastChange.push({ id: this.mapChokidarActionToSchemaId(action), values: { action: this.mapChokidarActionToGeneratedAction(action), path, name: pathUtil.basename(path), }, }) if (this.timeoutId) { clearTimeout(this.timeoutId) } this.timeoutId = setTimeout(async () => { await this.fireChange() }, options?.delay ?? 500) }) } private mapChokidarActionToSchemaId( action: ChokidarAction ): GeneratedFileOrDir['id'] { return action.search(/dir/gi) > -1 ? 'generatedDir' : 'generatedFile' } private mapChokidarActionToGeneratedAction(chokidar: ChokidarAction) { const map = { add: 'generated', addDir: 'generated', change: 'updated', unlink: 'deleted', unlinkDir: 'deleted', } return map[chokidar] as GeneratedFile['action'] } private async fireChange() { const changes = this.changesSinceLastChange this.changesSinceLastChange = [] await this.emitter.emitAndFlattenResponses( 'watcher.did-detect-change', { changes, } ) } public async stopWatching() { this._isWatching = false await this.watcher?.close() } } type ChokidarAction = 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir' declare module '../../features/features.types' { interface FeatureMap { watch: WatchFeature } interface FeatureOptionsMap { watch: undefined } }