@thi.ng/file-io
Version:
Assorted file I/O utils (w/ logging support) for NodeJS/Bun
117 lines (116 loc) • 3.33 kB
JavaScript
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
};