-
Notifications
You must be signed in to change notification settings - Fork 0
/
dir-tree.js
87 lines (69 loc) · 3.46 KB
/
dir-tree.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
/* jshint esnext: true */
var fs = require('fs'),
Emitter = require('events').EventEmitter,
emitter = new Emitter(),
eventState = require('event-state'),
dirTree = function (path, ignoreGlob, cb) {
var tree = {},
state,
callback = [].slice.call(arguments, -1)[0];
callback = (typeof callback === 'function') ? callback : undefined;
//TODO: implement igore globbing.
ignoreGlob = ignoreGlob || 'node_modules';
return buildBranch(path, tree);
function buildBranch(path, branch) {
return new Promise(function (res, rej) {
fs.readdir(path, function (err, files) {
if (err) {
//Errors result in a false value in the tree.
branch[path] = false;
rej(tree);
} else {
var newEvents = files.map(function (file) {
return path + '/' + file;
});
if (!state) {
// If this is the first iteration,
// initialize the dynamic state machine (DSM).
state = emitter.required(newEvents, function () {
// Allow for multiple paradigms vis-a-vis callback and promises.
// if a callback was passed, execute it passing it the completed tree.
callback && callback(tree);
// resolve the promise with the completed tree..
res(tree);
});
} else {
// Add events to the DSM for the directory's children
state.add(newEvents);
}
// Check each file descriptor to see if it's a directory.
files.forEach(function (file) {
var filePath = path + '/' + file;
fs.stat(filePath, function (err, stats) {
if (err) {
// Errors result in a false value in the tree
branch[file] = false;
emitter.emit(filePath, true);
} else if (stats.isDirectory()) {
// Directories are object properties on the tree.
branch[file] = {};
// Recurse into the directory.
buildBranch(filePath, branch[file]);
} else {
// If it's not a directory, it's a file.
// Files get a true value in the tree.
branch[file] = true;
emitter.emit(filePath, true);
}
});
});
}
//Once we've read the directory, we can raise the event for the parent
// directory and let it's children take care of themselves.
emitter.emit(path, true);
});
});
}
};
emitter.required = eventState;
module.exports = dirTree;