///
///
///
import { EventEmitter } from "events";
import { Stats } from "fs";
import { Matcher, Pattern } from "./matcher";
/**
* 表示一个文件系统监听器
* @description
* 本监听器的设计目标是:只针对常见场景,提供轻量、高效、稳定的实现,确保占用 CPU 极低且占用内存极小
*
* 1. 完全基于原生的 `fs.watch` 实现,低于 Node 10.12 版本不保证稳定性
* 2. 可监听文件或文件夹(同时监听子文件夹),可动态调整监听列表,但监听的根路径必须已存在且不能删除
* 3. 仅支持文件的增、删、改事件和文件夹的增、删事件,重命名操作会按先删除后创建处理
* 4. 文件软链和硬链始终会被替换为链接的目标路径,循环链接会引发错误
* 5. 在不支持 `fs.watch` 的系统(比如虚拟机)可开启 `usePolling`(基于原生 `fs.watchFile` 实现),但这会占用较高 CPU
*
* 如果以上不符合你的需求,请考虑使用 [chokidar](https://www.npmjs.com/package/chokidar)
*
* @example
* const watcher = new FileSystemWatcher()
* watcher.on("change", path => { console.log("Changed", path) })
* watcher.on("delete", path => { console.log("Deleted", path) })
* watcher.on("create", path => { console.log("Created", path) })
* watcher.add(process.cwd(), () => { console.log("Start Watching...") })
*/
export declare class FileSystemWatcher extends EventEmitter {
/**
* 初始化新的监听器
* @param options 附加选项
*/
constructor(options?: FileSystemWatcherOptions);
/** 所有原生监听器对象,键为监听的路径,值为原生监听器对象 */
private readonly _watchers;
/**
* 添加要监听的文件或文件夹
* @param path 要添加的文件或文件夹路径
* @param callback 添加完成的回调函数,在回调执行前无法监听到文件的修改
* @param callback.error 如果添加成功则为空,否则为错误对象
*/
add(path: string, callback?: (error: NodeJS.ErrnoException | null) => void): boolean;
/** 判断是否强制使用轮询监听,轮询监听可以支持更多的文件系统,但会占用大量 CPU */
readonly usePolling: boolean;
/** 获取或设置传递给原生监听器的选项 */
watchOptions: {
/** 是否在监听时阻止进程退出 */
persistent: boolean;
/** 是否使用原生的递归监听支持 */
recursive: boolean;
/** 轮询的间隔毫秒数 */
interval: number;
};
/**
* 创建指定路径的原生监听器
* @param path 要监听的文件或文件夹路径
* @param initStats 是否初始化路径对应的状态
* @param callback 创建完成的回调函数,在回调执行前无法监听到文件的修改
* @param callback.error 如果创建成功则为空,否则为相关的错误
* @returns 返回监听器
*/
private _createWatcher;
/**
* 创建指定路径的轮询监听器
* @param path 要监听的文件或文件夹路径
* @param initStats 是否初始化路径对应的状态
* @param callback 创建完成的回调函数,在回调执行前无法监听到文件的修改
* @param callback.error 如果创建成功则为空,否则为相关的错误
* @returns 返回监听器
*/
private _createPollingWatcher;
/**
* 所有文件或文件夹状态,对象的键是路径
* - 如果路径是一个文件,则值为文件的最后修改时间戳
* - 如果路径是一个文件夹,则值为所有直接子文件和子文件夹的名称数组
*/
private readonly _stats;
/** 正在执行的异步任务数 */
private _pending;
/**
* 初始化指定文件或文件夹的状态
* @param path 要添加的文件或文件夹路径
* @param isFile 是否优先将路径作为文件处理
* @param callback 已添加完成的回调函数
* @param depth 遍历的深度
*/
private _initStats;
/** 通知所有异步任务已执行结束 */
private _emitReady;
/**
* 当所有异步任务已执行结束执行
*/
protected onReady(): void;
/**
* 等待所有异步任务都完成后执行指定的回调函数
* @param callback 要执行的回调函数
*/
ready(callback: () => void): void;
/** 忽略匹配器 */
readonly ignoreMatcher: Matcher;
/**
* 判断是否忽略指定的路径
* @param path 要判断的文件或文件夹路径,路径的分隔符同操作系统
*/
ignored(path: string): boolean;
/**
* 判断是否正在监听指定的文件或文件夹
* @param path 要判断的路径
*/
isWatchingPath(path: string): boolean;
/** 判断当前监听器是否正在监听 */
get isWatching(): boolean;
/**
* 移除指定路径的监听器
* @param path 要移除的文件或文件夹路径
* @param callback 移除完成后的回调函数
* @description 注意如果已监听路径所在的文件夹,移除操作将无效
*/
remove(path: string, callback?: () => void): boolean;
/**
* 删除指定路径的原生监听器
* @param path 要删除监听的文件或文件夹路径
*/
private _deleteWatcher;
/**
* 移除已添加的所有监听器
* @param callback 移除完成后的回调函数
*/
close(callback?: () => void): void;
/** 暂停更新的次数 */
private _pauseCount;
/** 判断当前监听器是否已赞同触发事件 */
get paused(): boolean;
/** 暂停触发监听事件 */
pause(): void;
/** 恢复触发监听事件 */
resume(): void;
/** 所有已更新但未处理的文件或文件夹路径 */
private _pendingUpdates;
/** 是否正在使用 _pendingUpdates */
private _pendingUpdatesLocked;
/** 等待处理更新的计时器 */
private _emitUpdatesTimer?;
/** 获取或设置监听延时回调的毫秒数 */
delay: number;
/** 判断或设置是否仅当文件的最后修改时间发生变化才触发更新 */
compareModifyTime: boolean;
/**
* 处理原生更改事件
* @param path 更改的文件或文件夹路径
*/
protected handleWatchChange(path: string): void;
/** 处理所有更新 */
private _emitUpdates;
/**
* 更新指定文件或文件夹的状态
* @param path 要更新的文件或文件夹路径
* @param isFile 是否优先将路径作为文件处理
* @param force 是否强制更新文件
* @param pendingUpdates 本次同时更新的所有路径,提供此参数可避免重复更新
*/
private _emitUpdate;
/**
* 删除指定文件或文件夹
* @param path 要删除的文件或文件夹路径
* @param pendingUpdates 本次同时更新的所有路径,提供此参数可避免重复更新
*/
private _emitDelete;
/** 通知更新结束 */
private _endUpdate;
/**
* 当监听到文件夹创建后执行
* @param path 相关的文件夹路径
* @param entries 文件夹内的文件列表
*/
protected onCreateDir(path: string, entries: string[]): void;
/**
* 当监听到文件夹删除后执行
* @param path 相关的文件夹路径
* @param prevEntries 文件夹被删除前的文件列表
*/
protected onDeleteDir(path: string, prevEntries: string[]): void;
/**
* 当监听到文件创建后执行
* @param path 相关的文件路径
* @param stats 文件属性对象
*/
protected onCreate(path: string, stats: Stats): void;
/**
* 当监听到文件修改后执行
* @param path 相关的文件路径
* @param stats 相关的文件属性对象
* @param prevWriteTime 文件的上一次修改时间戳
*/
protected onChange(path: string, stats: Stats, prevWriteTime: number): void;
/**
* 当监听到文件删除后执行
* @param path 相关的文件路径
* @param prevWriteTime 文件被删除前最后一次的修改时间戳
*/
protected onDelete(path: string, prevWriteTime: number): void;
/**
* 当监听发生错误后执行
* @param error 相关的错误对象
* @param path 原始监听的路径
*/
protected onError(error: NodeJS.ErrnoException, path: string): void;
}
/** 表示监听器的附加选项 */
export interface FileSystemWatcherOptions {
/**
* 监听延时回调的毫秒数
* @description 设置一定的延时可以避免在短时间内重复处理相同的文件
* @default 2500
*/
delay?: number;
/**
* 是否在监听时阻止进程退出
* @default true
*/
persistent?: boolean;
/**
* 是否强制使用轮询监听,轮询监听可以支持更多的文件系统,但会占用大量 CPU
* @default process.platform !== "win32" && process.platform !== "darwin" && process.platform !== "linux" && process.platform !== "aix"
*/
usePolling?: boolean;
/**
* 轮询的间隔毫秒数
* @default 512
*/
interval?: number;
/**
* 是否仅当文件的最后修改时间发生变化才触发更新
* @default false
*/
compareModifyTime?: boolean;
/**
* 指定监听时忽略哪些文件,可以是通配符或正则表达式
* @default [".DS_Store", "Desktop.ini", "Thumbs.db", "ehthumbs.db", "*~", "*.tmp", ".git", ".vs"]
*/
ignore?: Pattern;
}