UNPKG

@thi.ng/file-io

Version:

Assorted file I/O utils (w/ logging support) for NodeJS/Bun

117 lines (116 loc) 3.33 kB
var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __decorateClass = (decorators, target, key, kind) => { var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target; for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result; if (kind && result) __defProp(target, key, result); return result; }; import { INotifyMixin } from "@thi.ng/api"; import { isString } from "@thi.ng/checks/is-string"; import { NULL_LOGGER } from "@thi.ng/logger/null"; import { existsSync, watch } from "node:fs"; import { join } from "node:path"; import { isDirectory } from "./dir.js"; import { __ensurePred } from "./internal/ensure.js"; import { maskedPath } from "./mask.js"; const EVENT_ADDED = "added"; const EVENT_CHANGED = "changed"; const EVENT_REMOVED = "removed"; let Watcher = class { watchers = {}; opts; _signal = false; constructor(opts) { this.opts = { logger: NULL_LOGGER, delay: 100, ...opts }; } addAll(paths) { for (let p of paths) { isString(p) ? this.add(p) : this.add(...p); } } add(path, opts) { if (this.watchers[path]) return false; const isDir = isDirectory(path); const pred = __ensurePred(opts?.ext || ""); this.opts.logger.debug(`adding watcher for:`, maskedPath(path)); this.watchers[path] = watch( path, { recursive: opts?.recursive !== false }, (event, currPath) => { if (!currPath) return; currPath = isDir ? join(path, currPath) : path; if (!pred(currPath)) return; setTimeout(() => { const mpath = maskedPath(currPath); if (event === "change") { this.opts.logger.info(`file changed: ${mpath}`); this.notify({ id: EVENT_CHANGED, value: currPath }); } else if (!isDir || path === currPath) { this.opts.logger.info(`file removed: ${mpath}`); this.notify({ id: EVENT_REMOVED, value: path }); this.remove(path); } else { const id = existsSync(currPath) ? EVENT_ADDED : EVENT_REMOVED; this.opts.logger.info(`file ${id}: ${mpath}`); this.notify({ id, value: currPath }); } }, this.opts.delay); } ); return true; } remove(path) { const watcher = this.watchers[path]; if (!watcher) return false; this.opts.logger.debug(`removing watcher for:`, maskedPath(path)); watcher.close(); delete this.watchers[path]; return true; } removeAll(paths) { for (let p of paths) { this.remove(p); } } clear() { this.removeAll(Object.keys(this.watchers)); } installSignalHandler() { if (!this._signal) { process.on("SIGINT", () => this.clear()); this._signal = true; } } // @ts-ignore mixin addListener(id, fn, scope) { } // @ts-ignore mixin removeListener(id, fn, scope) { } // @ts-ignore mixin notify(event) { } }; Watcher = __decorateClass([ INotifyMixin ], Watcher); const fileWatcher = (opts) => new Watcher(opts); export { EVENT_ADDED, EVENT_CHANGED, EVENT_REMOVED, Watcher, fileWatcher };