@graphprotocol/graph-cli
Version:
CLI for building for and deploying to The Graph
74 lines (73 loc) • 2.6 kB
JavaScript
import path from 'node:path';
import chokidar from 'chokidar';
export default class Watcher {
onReady;
onTrigger;
onCollectFiles;
onError;
watcher;
constructor(options) {
const { onReady, onTrigger, onCollectFiles, onError } = options;
this.onReady = onReady;
this.onTrigger = onTrigger;
this.onCollectFiles = onCollectFiles;
this.onError = onError;
}
async watch() {
// Collect files to watch
const files = await this.onCollectFiles();
// Initialize watcher
this.watcher = chokidar.watch(files, {
persistent: true,
ignoreInitial: true,
atomic: 500,
});
// Bind variables locally
const watcher = this.watcher;
const onTrigger = this.onTrigger;
const onCollectFiles = this.onCollectFiles;
const onError = this.onError;
const onReady = this.onReady;
watcher.on('ready', async () => {
// Notify listeners that we're watching
onReady();
// Trigger once when ready
onTrigger(undefined);
});
watcher.on('error', (error) => {
onError(error);
});
watcher.on('all', async (_, file) => {
try {
// Collect watch all new files to watch
const newFiles = await onCollectFiles();
// Collect watched files, if there are any
let watchedFiles = [];
const watched = watcher.getWatched();
watchedFiles = Object.keys(watched).reduce((files, dirname) => watched[dirname].reduce((files, filename) => {
files.push(path.resolve(path.join(dirname, filename)));
return files;
}, files), []);
const diff = (xs, ys) => ({
added: ys.filter((y) => !xs.includes(y)),
removed: xs.filter((x) => !ys.includes(x)),
});
// Diff previously watched files and new files; then remove and
// add files from/to the watcher accordingly
const filesDiff = diff(watchedFiles, newFiles);
watcher.unwatch(filesDiff.removed);
watcher.add(filesDiff.added);
// Run the trigger callback
onTrigger(file);
}
catch (e) {
onError(e);
}
});
}
close() {
if (this.watcher !== undefined) {
this.watcher.close();
}
}
}