0
# Event System & Control
1
2
Event emitter interface providing comprehensive file system events and flow control methods for directory traversal operations.
3
4
## Capabilities
5
6
### WalkEmitter Interface
7
8
The emitter returned by walkdir provides fine-grained control over the traversal process.
9
10
```javascript { .api }
11
/**
12
* Extended EventEmitter with walkdir-specific control methods
13
*/
14
interface WalkEmitter extends EventEmitter {
15
/** Stop the walk immediately and prevent further events */
16
end(): void;
17
/** Alias for end() - stop the walk immediately */
18
stop(): void;
19
/** Pause event emission while keeping traversal active */
20
pause(): void;
21
/** Resume event emission after pause */
22
resume(): void;
23
/** Ignore specific paths during traversal */
24
ignore(paths: string | string[]): void;
25
}
26
```
27
28
**Usage Examples:**
29
30
```javascript
31
const walkdir = require('walkdir');
32
33
const emitter = walkdir('./my-directory');
34
35
// Stop after finding 100 files
36
let fileCount = 0;
37
emitter.on('file', (path, stat) => {
38
fileCount++;
39
if (fileCount >= 100) {
40
emitter.end(); // Stop immediately
41
}
42
});
43
44
// Pause and resume based on system load
45
emitter.on('directory', (path, stat) => {
46
if (isSystemBusy()) {
47
emitter.pause();
48
setTimeout(() => emitter.resume(), 1000);
49
}
50
});
51
52
// Ignore specific directories dynamically
53
emitter.on('directory', (path, stat) => {
54
if (path.includes('node_modules') || path.includes('.git')) {
55
emitter.ignore(path); // Skip this directory and all children
56
}
57
});
58
```
59
60
### Core Events
61
62
Events emitted for different types of file system objects found during traversal.
63
64
```javascript { .api }
65
/**
66
* All events follow the pattern: (path: string, stat: fs.Stats, depth: number)
67
*/
68
69
/** Emitted for every file system object found */
70
emitter.on('path', (path, stat, depth) => {});
71
72
/** Emitted only for regular files */
73
emitter.on('file', (path, stat, depth) => {});
74
75
/** Emitted only for directories */
76
emitter.on('directory', (path, stat, depth) => {});
77
78
/** Emitted only for symbolic links */
79
emitter.on('link', (path, stat, depth) => {});
80
81
/** Emitted for the initial target directory (if it's a directory) */
82
emitter.on('targetdirectory', (path, stat, depth) => {});
83
84
/** Emitted when a directory is empty */
85
emitter.on('empty', (path, stat, depth) => {});
86
87
/** Emitted when traversal completes successfully */
88
emitter.on('end', () => {});
89
```
90
91
**Usage Examples:**
92
93
```javascript
94
const emitter = walkdir('./project');
95
96
// Process different file types
97
emitter.on('file', (path, stat, depth) => {
98
if (path.endsWith('.js')) {
99
console.log('JavaScript file:', path, 'at depth', depth);
100
}
101
});
102
103
emitter.on('directory', (path, stat, depth) => {
104
console.log('Directory:', path, 'contains', stat.size, 'entries');
105
});
106
107
emitter.on('link', (path, stat, depth) => {
108
console.log('Symbolic link found:', path);
109
});
110
111
// Handle completion
112
emitter.on('end', () => {
113
console.log('Directory traversal completed');
114
});
115
116
// Track progress
117
let totalItems = 0;
118
emitter.on('path', () => {
119
totalItems++;
120
if (totalItems % 100 === 0) {
121
console.log(`Processed ${totalItems} items...`);
122
}
123
});
124
```
125
126
### Special Device Events
127
128
Events for special file system objects like sockets, fifos, and devices.
129
130
```javascript { .api }
131
/** Emitted for socket descriptors */
132
emitter.on('socket', (path, stat, depth) => {});
133
134
/** Emitted for FIFO/named pipes */
135
emitter.on('fifo', (path, stat, depth) => {});
136
137
/** Emitted for block devices */
138
emitter.on('blockdevice', (path, stat, depth) => {});
139
140
/** Emitted for character devices */
141
emitter.on('characterdevice', (path, stat, depth) => {});
142
```
143
144
**Usage Example:**
145
146
```javascript
147
const emitter = walkdir('/dev');
148
149
emitter.on('blockdevice', (path, stat) => {
150
console.log('Block device (disk):', path);
151
});
152
153
emitter.on('characterdevice', (path, stat) => {
154
console.log('Character device (terminal/tty):', path);
155
});
156
157
emitter.on('socket', (path, stat) => {
158
console.log('Socket found:', path);
159
});
160
```
161
162
### Error Events
163
164
Error handling events for various failure scenarios during traversal.
165
166
```javascript { .api }
167
/** Emitted for fatal errors reading the target directory */
168
emitter.on('error', (error) => {});
169
170
/** Emitted for non-fatal errors reading nested paths */
171
emitter.on('fail', (path, error) => {});
172
173
/** Emitted when maximum depth is reached */
174
emitter.on('maxdepth', (path, stat, depth) => {});
175
```
176
177
**Error Handling Examples:**
178
179
```javascript
180
const emitter = walkdir('./some-directory');
181
182
// Handle fatal errors (target directory issues)
183
emitter.on('error', (error) => {
184
console.error('Fatal error - cannot read target directory:', error.message);
185
process.exit(1);
186
});
187
188
// Handle non-fatal errors (permission issues, corrupt files, etc.)
189
emitter.on('fail', (path, error) => {
190
console.warn('Could not access path:', path, '-', error.message);
191
// Continue processing other paths
192
});
193
194
// Handle depth limits
195
emitter.on('maxdepth', (path, stat, depth) => {
196
console.log('Reached maximum depth at:', path, 'depth:', depth);
197
// Note: traversal continues but won't go deeper into this path
198
});
199
200
// Graceful error handling
201
let errorCount = 0;
202
emitter.on('fail', (path, error) => {
203
errorCount++;
204
if (errorCount > 10) {
205
console.warn('Too many errors, stopping traversal');
206
emitter.end();
207
}
208
});
209
```
210
211
### Flow Control Methods
212
213
Methods for controlling the traversal process dynamically.
214
215
```javascript { .api }
216
/**
217
* Stop the walk immediately
218
* No more events will be emitted after calling end()
219
*/
220
emitter.end();
221
222
/**
223
* Alias for end() - stop the walk immediately
224
* Same functionality as end()
225
*/
226
emitter.stop();
227
228
/**
229
* Pause event emission
230
* Traversal continues but events are queued until resume()
231
*/
232
emitter.pause();
233
234
/**
235
* Resume event emission after pause
236
* Queued events will be emitted in order
237
*/
238
emitter.resume();
239
240
/**
241
* Ignore specific paths during traversal
242
* Ignored directories will not be entered or have children processed
243
* @param {string|string[]} paths - Path or array of paths to ignore
244
*/
245
emitter.ignore(paths);
246
```
247
248
**Flow Control Examples:**
249
250
```javascript
251
const emitter = walkdir('./large-project');
252
253
// Conditional stopping
254
emitter.on('file', (path, stat) => {
255
if (path.endsWith('.exe') && stat.size > 100 * 1024 * 1024) {
256
console.log('Found large executable, stopping scan');
257
emitter.end();
258
}
259
});
260
261
// Throttling with pause/resume
262
let processedCount = 0;
263
emitter.on('path', (path, stat) => {
264
processedCount++;
265
266
// Pause every 1000 items to prevent overwhelming
267
if (processedCount % 1000 === 0) {
268
emitter.pause();
269
setTimeout(() => {
270
console.log(`Processed ${processedCount} items, resuming...`);
271
emitter.resume();
272
}, 100);
273
}
274
});
275
276
// Dynamic path ignoring
277
const ignoredPaths = [];
278
emitter.on('directory', (path, stat) => {
279
if (path.includes('cache') || path.includes('temp')) {
280
ignoredPaths.push(path);
281
emitter.ignore(path);
282
console.log('Ignoring cache/temp directory:', path);
283
}
284
});
285
286
// Bulk ignore patterns
287
emitter.on('targetdirectory', () => {
288
// Ignore common build/cache directories upfront
289
emitter.ignore([
290
'./node_modules',
291
'./.git',
292
'./build',
293
'./dist',
294
'./.cache'
295
]);
296
});
297
```
298
299
### Event Chaining Patterns
300
301
Common patterns for combining events and control methods.
302
303
```javascript
304
// Progress reporting with early termination
305
const emitter = walkdir('./project');
306
let startTime = Date.now();
307
let itemCount = 0;
308
309
emitter.on('path', (path, stat) => {
310
itemCount++;
311
312
// Progress every 500 items
313
if (itemCount % 500 === 0) {
314
const elapsed = (Date.now() - startTime) / 1000;
315
console.log(`${itemCount} items processed in ${elapsed}s`);
316
}
317
318
// Stop after 10 seconds
319
if (Date.now() - startTime > 10000) {
320
console.log('Time limit reached, stopping');
321
emitter.end();
322
}
323
});
324
325
emitter.on('end', () => {
326
const elapsed = (Date.now() - startTime) / 1000;
327
console.log(`Completed: ${itemCount} items in ${elapsed}s`);
328
});
329
```