78 lines
No EOL
2.5 KiB
TypeScript
78 lines
No EOL
2.5 KiB
TypeScript
import { FSWatcher, watch } from 'fs';
|
|
import { promises } from 'fs';
|
|
import event from 'events';
|
|
|
|
|
|
const readdir = promises.readdir;
|
|
|
|
interface DiffWatcherEvent{
|
|
'create':(filename:string)=>void,
|
|
'delete':(filename:string)=>void,
|
|
'change':(prev_filename:string,cur_filename:string)=>void,
|
|
}
|
|
|
|
export interface IDiffWatcher extends event.EventEmitter {
|
|
on<U extends keyof DiffWatcherEvent>(event:U,listener:DiffWatcherEvent[U]): this;
|
|
emit<U extends keyof DiffWatcherEvent>(event:U,...arg:Parameters<DiffWatcherEvent[U]>): boolean;
|
|
readonly path: string;
|
|
}
|
|
|
|
export class CommonDiffWatcher extends event.EventEmitter implements IDiffWatcher{
|
|
on<U extends keyof DiffWatcherEvent>(event:U,listener:DiffWatcherEvent[U]): this{
|
|
return super.on(event,listener);
|
|
}
|
|
emit<U extends keyof DiffWatcherEvent>(event:U,...arg:Parameters<DiffWatcherEvent[U]>): boolean{
|
|
return super.emit(event,...arg);
|
|
}
|
|
private _path:string;
|
|
private _watcher: FSWatcher|null;
|
|
|
|
constructor(path:string){
|
|
super();
|
|
this._path = path;
|
|
this._watcher = null;
|
|
}
|
|
public get path(){
|
|
return this._path;
|
|
}
|
|
/**
|
|
* setup
|
|
* @argument initial_filenames filename in path
|
|
*/
|
|
async setup(initial_filenames:string[]){
|
|
const cur = (await readdir(this._path,{
|
|
encoding:"utf8",
|
|
withFileTypes: true,
|
|
})).filter(x=>x.isFile).map(x=>x.name);
|
|
//Todo : reduce O(nm) to O(n+m) using hash map.
|
|
let added = cur.filter(x => !initial_filenames.includes(x));
|
|
let deleted = initial_filenames.filter(x=>!cur.includes(x));
|
|
for (const iterator of added) {
|
|
this.emit('create',iterator);
|
|
}
|
|
for (const iterator of deleted){
|
|
this.emit('delete',iterator);
|
|
}
|
|
}
|
|
watch():FSWatcher{
|
|
this._watcher = watch(this._path,{persistent: true, recursive:false},async (eventType,filename)=>{
|
|
if(eventType === "rename"){
|
|
const cur = (await readdir(this._path,{
|
|
encoding:"utf8",
|
|
withFileTypes: true,
|
|
})).filter(x=>x.isFile).map(x=>x.name);
|
|
//add
|
|
if(cur.includes(filename)){
|
|
this.emit('create',filename);
|
|
}
|
|
else{
|
|
this.emit('delete',filename)
|
|
}
|
|
}
|
|
});
|
|
return this._watcher;
|
|
}
|
|
watchClose(){
|
|
this._watcher?.close()
|
|
}
|
|
} |