/
fileWatcher.ts
66 lines (60 loc) · 2.07 KB
/
fileWatcher.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import { platform } from 'node:os';
import chokidar, { type FSWatcher } from 'chokidar';
import type { ChangeEvent, ChokidarOptions } from '../rollup/types';
import type { Task } from './watch';
export class FileWatcher {
private readonly chokidarOptions: ChokidarOptions;
private readonly task: Task;
private readonly transformWatchers = new Map<string, FSWatcher>();
private readonly watcher: FSWatcher;
constructor(task: Task, chokidarOptions: ChokidarOptions) {
this.chokidarOptions = chokidarOptions;
this.task = task;
this.watcher = this.createWatcher(null);
}
close(): void {
this.watcher.close();
for (const watcher of this.transformWatchers.values()) {
watcher.close();
}
}
unwatch(id: string): void {
this.watcher.unwatch(id);
const transformWatcher = this.transformWatchers.get(id);
if (transformWatcher) {
this.transformWatchers.delete(id);
transformWatcher.close();
}
}
watch(id: string, isTransformDependency: boolean): void {
if (isTransformDependency) {
const watcher = this.transformWatchers.get(id) ?? this.createWatcher(id);
watcher.add(id);
this.transformWatchers.set(id, watcher);
} else {
this.watcher.add(id);
}
}
private createWatcher(transformWatcherId: string | null): FSWatcher {
const task = this.task;
const isLinux = platform() === 'linux';
const isTransformDependency = transformWatcherId !== null;
const handleChange = (id: string, event: ChangeEvent) => {
const changedId = transformWatcherId || id;
if (isLinux) {
// unwatching and watching fixes an issue with chokidar where on certain systems,
// a file that was unlinked and immediately recreated would create a change event
// but then no longer any further events
watcher.unwatch(changedId);
watcher.add(changedId);
}
task.invalidate(changedId, { event, isTransformDependency });
};
const watcher = chokidar
.watch([], this.chokidarOptions)
.on('add', id => handleChange(id, 'create'))
.on('change', id => handleChange(id, 'update'))
.on('unlink', id => handleChange(id, 'delete'));
return watcher;
}
}