-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
106 lines (81 loc) · 2.26 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import fs from "fs";
import { EventEmitter } from "events";
import util from "util";
const stat = util.promisify(fs.stat);
const tasks = new Map();
const register = (main, prop, listener) =>
(main[prop] = new Set(
main[prop] instanceof Set ? main[prop] : [main[prop]]
).add(listener));
const walk = (val, fn) => (val instanceof Set ? val.forEach(fn) : fn(val));
const isFileModified = (curr, prev) => {
const currmTime = curr.mtimeMs;
return curr.size !== prev.size || currmTime > prev.mtimeMs || currmTime === 0;
};
const createTask = (path, listener, notifier) => {
const task = {
listeners: listener,
notifiers: notifier,
watcher: fs.watchFile(path, (curr, prev) => {
walk(task.notifiers, (notifier) => notifier("changed file"));
if (isFileModified(curr, prev)) {
walk(task.listeners, (listener) => listener(path, curr));
}
}),
};
return task;
};
function watchFile(path, { listener, notifier }) {
const task = tasks.get(path);
if (task) {
register(task, "listeners", listener);
register(task, "notifiers", notifier);
} else {
tasks.set(path, createTask(path, listener, notifier));
}
}
function watcherApi(bus) {
const watch = (path, listener) => {
let closer;
closer = watchFile(path, {
listener,
notifier: (ev, payload) => bus.emit(ev, payload),
});
return closer;
};
const monitor = (file, stats) => {
let prevStats = stats;
const listener = async (path, newStats) => {
try {
const newStats = await stat(file);
const at = newStats.atimeMs;
const mt = newStats.mtimeMs;
if (!at || at <= mt || mt !== prevStats.mtimeMs) {
bus.emit("change", file);
}
} catch (error) {
console.log(error);
}
};
watch(file, listener);
};
const add = async (path) => {
const stats = await stat(path);
if (stats.isFile()) monitor(path, stats);
};
return {
add,
};
}
function watch() {
const dirs = [];
const cwd = process.cwd();
if (!dirs.length) dirs.unshift(`${cwd}/teste.txt`);
const bus = new EventEmitter();
const api = watcherApi(bus);
dirs.forEach((dir) => api.add(dir));
return bus;
}
watch().on("change", (file) => {
console.log("file changed: ", file);
});