-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchokidar.js
178 lines (123 loc) · 3.58 KB
/
chokidar.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
const fs = require("fs");
const server = require("./server.js");
let watches = [];
// fake-chokidar was made specifically for Webpack and the options used by it.
// The following watch() options are what fake-chokidar expects. It should
// be possible to allow different options, but these would need to be
// implemented first, of course.
const expectedOpts = {
ignoreInitial: true,
persistent: true,
followSymlinks: false,
depth: 0, // important
atomic: false,
usePolling: undefined,
interval: undefined,
binaryInterval: undefined,
disableGlobbing: true
};
/**
* Tweaks the "chokidar" module by replacing it's watch() method.
*
* This must be called at the very beginning of the program, ie. at the top
* of your webpack.config.js
*
* Available options:
*
* `port`: UDP port to listen for events. Defaults to 49494 but you might
* want to choose a specific port. The port number must match the one used
* by `fake-chokidar-sender`.
*
* `host`: Host to bind the UDP event server on. Defaults to '0.0.0.0' (all
* interfaces) and should be fine for normal situations.
*
* `chokidar`: Reference to the 'chokidar' module. If not given, default
* Chokidar is used. Normally there is no need to use this option.
*
*
* @param options
*/
exports.inject = function(options) {
options = options || {};
// NB: "chokidar" is *not* in our package.json
const chokidar = options.chokidar || require("chokidar");
server.initServer(options, handleMessage);
chokidar.watch = function(path, opts) {
checkWatchParameters(path, opts);
const listeners = [];
const myWatch = { listeners };
watches.push(myWatch);
return {
on: (event, func) => {
listeners.push({
path,
opts,
event,
func,
});
},
close: () => {
watches = watches.filter(x => x !== myWatch);
}
};
};
};
/**
* Checks whether the given watch() parameters are valid for this Chokidar
* emulation.
*
* Throws exceptions when it finds unusual settings.
*
* @param path
* @param opts
*/
function checkWatchParameters(path, opts) {
if (typeof path !== "string")
throw new Error("first argument expected to be a string");
for (const key of Object.keys(opts)) {
if (expectedOpts.hasOwnProperty(key) && opts[key] !== expectedOpts[key]) {
throw new Error("Unexpected value for option " + key + " (" + opts[key] + ")");
}
}
}
/**
* Handles a message received from fake-chokidar-sender.
*
* @param message - Raw UDP message.
*/
function handleMessage(message) {
const payload = JSON.parse(message);
const { event, path } = payload;
const basePath = path.substring(0, path.lastIndexOf("/"));
console.log(payload);
watches.forEach(({listeners}) => {
listeners
.filter(l => l.event === event && l.path === basePath)
.forEach(l => {
invokeListener(l, event, path);
});
});
}
/**
* Calls all registered Chokidar listeners matching the event.
*
* @param listener
* @param event
* @param path
*/
function invokeListener(listener, event, path) {
const call = stat => listener.func(path, stat);
if (['add', 'addDir','change'].indexOf(event) >= 0) {
// 'add', 'addDir' and 'change' events also receive stat() results as second
// argument when available: http://nodejs.org/api/fs.html#fs_class_fs_stats
fs.stat(path, (err, stat) => {
if (stat)
call(stat);
else
console.log("WARNING: Lost event [" + event + " " + path + "] due to" +
" failed stat()");
});
} else {
call();
}
}