/* IMPORT */ import { EventEmitter } from 'node:events'; import fs from 'node:fs'; import path from 'node:path'; import { DEPTH, LIMIT, HAS_NATIVE_RECURSION, POLLING_INTERVAL } from './constants.js'; import { TargetEvent, WatcherEvent } from './enums.js'; import Utils from './utils.js'; import WatcherHandler from './watcher_handler.js'; import WatcherLocker from './watcher_locker.js'; import WatcherPoller from './watcher_poller.js'; /* MAIN */ class Watcher extends EventEmitter { /* CONSTRUCTOR */ constructor(target, options, handler) { super(); this._closed = false; this._ready = false; this._closeAborter = new AbortController(); this._closeSignal = this._closeAborter.signal; this.on(WatcherEvent.CLOSE, () => this._closeAborter.abort()); this._closeWait = new Promise(resolve => this.on(WatcherEvent.CLOSE, resolve)); this._readyWait = new Promise(resolve => this.on(WatcherEvent.READY, resolve)); this._locker = new WatcherLocker(this); this._roots = new Set(); this._poller = new WatcherPoller(); this._pollers = new Set(); this._subwatchers = new Set(); this._watchers = {}; this._watchersLock = Promise.resolve(); this._watchersRestorable = {}; this.watch(target, options, handler); } /* API */ isClosed() { return this._closed; } isIgnored(targetPath, ignore) { return !!ignore && (Utils.lang.isFunction(ignore) ? !!ignore(targetPath) : ignore.test(targetPath)); } isReady() { return this._ready; } close() { this._locker.reset(); this._poller.reset(); this._roots.clear(); this.watchersClose(); if (this.isClosed()) return false; this._closed = true; return this.emit(WatcherEvent.CLOSE); } error(exception) { if (this.isClosed()) return false; const error = Utils.lang.castError(exception); return this.emit(WatcherEvent.ERROR, error); } event(event, targetPath, targetPathNext) { if (this.isClosed()) return false; this.emit(WatcherEvent.ALL, event, targetPath, targetPathNext); return this.emit(event, targetPath, targetPathNext); } ready() { if (this.isClosed() || this.isReady()) return false; this._ready = true; return this.emit(WatcherEvent.READY); } pollerExists(targetPath, options) { for (const poller of this._pollers) { if (poller.targetPath !== targetPath) continue; if (!Utils.lang.isShallowEqual(poller.options, options)) continue; return true; } return false; } subwatcherExists(targetPath, options) { for (const subwatcher of this._subwatchers) { if (subwatcher.targetPath !== targetPath) continue; if (!Utils.lang.isShallowEqual(subwatcher.options, options)) continue; return true; } return false; } watchersClose(folderPath, filePath, recursive = true) { if (!folderPath) { for (const folderPath in this._watchers) { this.watchersClose(folderPath, filePath, false); } } else { const configs = this._watchers[folderPath]; if (configs) { for (const config of [...configs]) { // It's important to clone the array, as items will be deleted from it also if (filePath && config.filePath !== filePath) continue; this.watcherClose(config); } } if (recursive) { for (const folderPathOther in this._watchers) { if (!Utils.fs.isSubPath(folderPath, folderPathOther)) continue; this.watchersClose(folderPathOther, filePath, false); } } } } watchersLock(callback) { return this._watchersLock.then(() => { return this._watchersLock = new Promise(async (resolve) => { await callback(); resolve(); }); }); } watchersRestore() { delete this._watchersRestoreTimeout; const watchers = Object.entries(this._watchersRestorable); this._watchersRestorable = {}; for (const [targetPath, config] of watchers) { this.watchPath(targetPath, config.options, config.handler); } } async watcherAdd(config, baseWatcherHandler) { const { folderPath } = config; const configs = this._watchers[folderPath] = (this._watchers[folderPath] || []); configs.push(config); const watcherHandler = new WatcherHandler(this, config, baseWatcherHandler); await watcherHandler.init(); return watcherHandler; } watcherClose(config) { config.watcher.close(); const configs = this._watchers[config.folderPath]; if (configs) { const index = configs.indexOf(config); configs.splice(index, 1); if (!configs.length) { delete this._watchers[config.folderPath]; } } const rootPath = config.filePath || config.folderPath; const isRoot = this._roots.has(rootPath); if (isRoot) { this._watchersRestorable[rootPath] = config; if (!this._watchersRestoreTimeout) { this._watchersRestoreTimeout = Utils.lang.defer(() => this.watchersRestore()); } } } watcherExists(folderPath, options, handler, filePath) { const configsSibling = this._watchers[folderPath]; if (!!configsSibling?.find(config => config.handler === handler && (!config.filePath || config.filePath === filePath) && config.options.ignore === options.ignore && !!config.options.native === !!options.native && (!options.recursive || config.options.recursive))) return true; let folderAncestorPath = path.dirname(folderPath); for (let depth = 1; depth < Infinity; depth++) { const configsAncestor = this._watchers[folderAncestorPath]; if (!!configsAncestor?.find(config => (depth === 1 || (config.options.recursive && depth <= (config.options.depth ?? DEPTH))) && config.handler === handler && (!config.filePath || config.filePath === filePath) && config.options.ignore === options.ignore && !!config.options.native === !!options.native && (!options.recursive || (config.options.recursive && (HAS_NATIVE_RECURSION && config.options.native !== false))))) return true; if (!HAS_NATIVE_RECURSION) break; // No other ancestor will possibly be found const folderAncestorPathNext = path.dirname(folderPath); if (folderAncestorPath === folderAncestorPathNext) break; folderAncestorPath = folderAncestorPathNext; } return false; } async watchDirectories(foldersPaths, options, handler, filePath, baseWatcherHandler) { if (this.isClosed()) return; foldersPaths = Utils.lang.uniq(foldersPaths).sort(); let watcherHandlerLast; for (const folderPath of foldersPaths) { if (this.isIgnored(folderPath, options.ignore)) continue; if (this.watcherExists(folderPath, options, handler, filePath)) continue; try { const watcherOptions = (!options.recursive || (HAS_NATIVE_RECURSION && options.native !== false)) ? options : { ...options, recursive: false }; // Ensuring recursion is explicitly disabled if not available const watcher = fs.watch(folderPath, watcherOptions); const watcherConfig = { watcher, handler, options, folderPath, filePath }; const watcherHandler = watcherHandlerLast = await this.watcherAdd(watcherConfig, baseWatcherHandler); const isRoot = this._roots.has(filePath || folderPath); if (isRoot) { const parentOptions = { ...options, ignoreInitial: true, recursive: false }; // Ensuring only the parent folder is being watched const parentFolderPath = path.dirname(folderPath); const parentFilePath = folderPath; await this.watchDirectories([parentFolderPath], parentOptions, handler, parentFilePath, watcherHandler); //TODO: Watch parents recursively with the following code, which requires other things to be changed too though // while ( true ) { // await this.watchDirectories ( [parentFolderPath], parentOptions, handler, parentFilePath, watcherHandler ); // const parentFolderPathNext = path.dirname ( parentFolderPath ); // if ( parentFolderPath === parentFolderPathNext ) break; // parentFilePath = parentFolderPath; // parentFolderPath = parentFolderPathNext; // } } } catch (error) { this.error(error); } } return watcherHandlerLast; } async watchDirectory(folderPath, options, handler, filePath, baseWatcherHandler) { if (this.isClosed()) return; if (this.isIgnored(folderPath, options.ignore)) return; if (!options.recursive || (HAS_NATIVE_RECURSION && options.native !== false)) { return this.watchersLock(() => { return this.watchDirectories([folderPath], options, handler, filePath, baseWatcherHandler); }); } else { options = { ...options, recursive: true }; // Ensuring recursion is explicitly enabled const depth = options.depth ?? DEPTH; const limit = options.limit ?? LIMIT; const [folderSubPaths] = await Utils.fs.readdir(folderPath, options.ignore, depth, limit, this._closeSignal, options.readdirMap); return this.watchersLock(async () => { const watcherHandler = await this.watchDirectories([folderPath], options, handler, filePath, baseWatcherHandler); if (folderSubPaths.length) { const folderPathDepth = Utils.fs.getDepth(folderPath); for (const folderSubPath of folderSubPaths) { const folderSubPathDepth = Utils.fs.getDepth(folderSubPath); const subDepth = Math.max(0, depth - (folderSubPathDepth - folderPathDepth)); const subOptions = { ...options, depth: subDepth }; // Updating the maximum depth to account for depth of the sub path await this.watchDirectories([folderSubPath], subOptions, handler, filePath, baseWatcherHandler || watcherHandler); } } }); } } async watchFileOnce(filePath, options, callback) { if (this.isClosed()) return; options = { ...options, ignoreInitial: false }; // Ensuring initial events are detected too if (this.subwatcherExists(filePath, options)) return; const config = { targetPath: filePath, options }; const handler = (event, targetPath) => { if (targetPath !== filePath) return; stop(); callback(); }; const watcher = new Watcher(handler); const start = () => { this._subwatchers.add(config); this.on(WatcherEvent.CLOSE, stop); // Ensuring the subwatcher is stopped on close watcher.watchFile(filePath, options, handler); }; const stop = () => { this._subwatchers.delete(config); this.removeListener(WatcherEvent.CLOSE, stop); // Ensuring there are no leftover listeners watcher.close(); }; return start(); } async watchFile(filePath, options, handler) { if (this.isClosed()) return; if (this.isIgnored(filePath, options.ignore)) return; options = { ...options, recursive: false }; // Ensuring recursion is explicitly disabled const folderPath = path.dirname(filePath); return this.watchDirectory(folderPath, options, handler, filePath); } async watchPollingOnce(targetPath, options, callback) { if (this.isClosed()) return; let isDone = false; const poller = new WatcherPoller(); const disposer = await this.watchPolling(targetPath, options, async () => { if (isDone) return; const events = await poller.update(targetPath, options.pollingTimeout); if (!events.length) return; // Nothing actually changed, skipping if (isDone) return; // Another async callback has done the work already, skipping isDone = true; disposer(); callback(); }); } async watchPolling(targetPath, options, callback) { if (this.isClosed()) return Utils.lang.noop; if (this.pollerExists(targetPath, options)) return Utils.lang.noop; const watcherOptions = { ...options, interval: options.pollingInterval ?? POLLING_INTERVAL }; // Ensuring a default interval is set const config = { targetPath, options }; const start = () => { this._pollers.add(config); this.on(WatcherEvent.CLOSE, stop); // Ensuring polling is stopped on close fs.watchFile(targetPath, watcherOptions, callback); }; const stop = () => { this._pollers.delete(config); this.removeListener(WatcherEvent.CLOSE, stop); // Ensuring there are no leftover listeners fs.unwatchFile(targetPath, callback); }; Utils.lang.attempt(start); return () => Utils.lang.attempt(stop); } async watchUnknownChild(targetPath, options, handler) { if (this.isClosed()) return; const watch = () => this.watchPath(targetPath, options, handler); return this.watchFileOnce(targetPath, options, watch); } async watchUnknownTarget(targetPath, options, handler) { if (this.isClosed()) return; const watch = () => this.watchPath(targetPath, options, handler); return this.watchPollingOnce(targetPath, options, watch); } async watchPaths(targetPaths, options, handler) { if (this.isClosed()) return; targetPaths = Utils.lang.uniq(targetPaths).sort(); const isParallelizable = targetPaths.every((targetPath, index) => targetPaths.every((t, i) => i === index || !Utils.fs.isSubPath(targetPath, t))); // All paths are about separate subtrees, so we can start watching in parallel safely //TODO: Find parallelizable chunks rather than using an all or nothing approach if (isParallelizable) { // Watching in parallel await Promise.all(targetPaths.map(targetPath => { return this.watchPath(targetPath, options, handler); })); } else { // Watching serially for (const targetPath of targetPaths) { await this.watchPath(targetPath, options, handler); } } } async watchPath(targetPath, options, handler) { if (this.isClosed()) return; targetPath = path.resolve(targetPath); if (this.isIgnored(targetPath, options.ignore)) return; const stats = await Utils.fs.poll(targetPath, options.pollingTimeout); if (!stats) { const parentPath = path.dirname(targetPath); const parentStats = await Utils.fs.poll(parentPath, options.pollingTimeout); if (parentStats?.isDirectory()) { return this.watchUnknownChild(targetPath, options, handler); } else { return this.watchUnknownTarget(targetPath, options, handler); } } else if (stats.isFile()) { return this.watchFile(targetPath, options, handler); } else if (stats.isDirectory()) { return this.watchDirectory(targetPath, options, handler); } else { this.error(`"${targetPath}" is not supported`); } } async watch(target, options, handler = Utils.lang.noop) { if (Utils.lang.isFunction(target)) return this.watch([], {}, target); if (Utils.lang.isUndefined(target)) return this.watch([], options, handler); if (Utils.lang.isFunction(options)) return this.watch(target, {}, options); if (Utils.lang.isUndefined(options)) return this.watch(target, {}, handler); if (this.isClosed()) return; if (this.isReady()) options.readdirMap = undefined; // Only usable before initialization const targetPaths = Utils.lang.castArray(target); targetPaths.forEach(targetPath => this._roots.add(targetPath)); await this.watchPaths(targetPaths, options, handler); if (this.isClosed()) return; if (handler !== Utils.lang.noop) { this.on(WatcherEvent.ALL, handler); } options.readdirMap = undefined; // Only usable before initialization this.ready(); } } /* EXPORT */ export default Watcher; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2F0Y2hlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3dhdGNoZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsWUFBWTtBQUVaLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxhQUFhLENBQUM7QUFDekMsT0FBTyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3pCLE9BQU8sSUFBSSxNQUFNLFdBQVcsQ0FBQztBQUM3QixPQUFPLEVBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxvQkFBb0IsRUFBRSxnQkFBZ0IsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQ3BGLE9BQU8sRUFBQyxXQUFXLEVBQUUsWUFBWSxFQUFDLE1BQU0sWUFBWSxDQUFDO0FBQ3JELE9BQU8sS0FBSyxNQUFNLFlBQVksQ0FBQztBQUMvQixPQUFPLGNBQWMsTUFBTSxzQkFBc0IsQ0FBQztBQUNsRCxPQUFPLGFBQWEsTUFBTSxxQkFBcUIsQ0FBQztBQUNoRCxPQUFPLGFBQWEsTUFBTSxxQkFBcUIsQ0FBQztBQUdoRCxVQUFVO0FBRVYsTUFBTSxPQUFRLFNBQVEsWUFBWTtJQW9CaEMsaUJBQWlCO0lBRWpCLFlBQWMsTUFBZ0MsRUFBRSxPQUFrQyxFQUFFLE9BQWlCO1FBRW5HLEtBQUssRUFBRyxDQUFDO1FBRVQsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDckIsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7UUFDcEIsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLGVBQWUsRUFBRyxDQUFDO1FBQzVDLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUM7UUFDOUMsSUFBSSxDQUFDLEVBQUUsQ0FBRyxZQUFZLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFHLENBQUUsQ0FBQztRQUNsRSxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksT0FBTyxDQUFHLE9B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