-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
108 lines (94 loc) · 3.56 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
107
108
const fs = require('fs');
const path = require('path');
const args = require('typeof-arguments');
const moveOn = require('move-on');
const type = require('of-type');
const cliError = (msg) => `\x1b[31m${msg}\x1b[0m`;
module.exports = function (p, b, c) {
const types = type(c, Function) ? [String, [Object], Function] : type(b, Function) ? [String, Function] : type(b, Object) ? [String, Object, Function] : [String, [Object, Function], [Function, undefined]];
args(arguments, types, (o) => {
var err = new TypeError(cliError(o.message));
throw err;
});
const getPath = path.resolve(p);
const config = type(b, Object) ? b : {};
const callback = type(b, Function) ? b : c;
const depth = type(config.depth, Number) ? config.depth : null;
var exclude = type(config.exclude, String) ? [config.exclude] : type(config.exclude, Array) ? config.exclude : [];
const context = { error: null, dirs: [], files: [], inaccessible: [], path: getPath };
moveOn([pathExists, prepareExcluded, explore], {context}, onDone, onCatch);
function onDone() {
callback(this);
}
function onCatch(context, err) {
this.error = err;
callback(this);
}
function pathExists(resolve, reject) {
itemExists(this.path, (o) => {
if (!o.exists) return reject(new Error(`The given path '${getPath}' does not exist or is inaccessible.`));
if (o.exists && o.file) return reject(new Error(`The given path '${getPath}' leads to the file, while it should indicate the folder.`));
if (!(o.exists && o.dir)) return reject(new Error(`Could not get the access to the given path '${getPath}'.`));
if (o.exists && o.dir) return resolve();
});
}
function prepareExcluded(resolve) {
exclude = exclude.map((o) => {
return path.normalize(o);
});
resolve();
}
function explore(resolve, reject, context, r, l) {
var relative = typeof r === 'undefined' ? './' : r;
var absolute = path.join(this.path, relative);
var deep = typeof l === 'undefined' ? 0 : l;
var nextDeep = deep + 1;
fs.readdir(absolute, (err, contents) => {
if (err) {
this.inaccessible.push(relative);
resolve();
}
if (!err) {
var contentsIter = 0;
contents = contents.filter((x) => {
const ind = exclude.indexOf(path.join(relative, x));
if (ind >= 0) exclude.splice(ind, 1);
return !(ind >= 0);
});
if (!contents.length) resolve();
for (let i in contents) {
checkItem.call(this, relative, contents[i], (isDir, relative) => {
if (isDir && nextDeep !== depth) return explore.call(this, iter, reject, context, relative, nextDeep);
iter();
}, resolve);
}
}
function iter() {
if (++contentsIter === contents.length) resolve();
}
});
}
function checkItem(r, item, resolve) {
var absolute = path.resolve(this.path, r, item);
var relative = path.join(r, item);
itemExists(absolute, (o) => {
if (o.error) this.inaccessible.push(relative);
if (o.file) this.files.push(relative);
if (o.dir) this.dirs.push(relative);
resolve(o.dir, relative);
});
}
function itemExists(getPath, callback) {
fs.stat(getPath, (err, stats) => {
var o = { error: null, exists: false, file: false, dir: false };
if (err) o.error = err;
if (!err) {
o.exists = err === null;
const hasStats = stats instanceof fs.Stats;
o.file = hasStats && stats.isFile();
o.dir = hasStats && stats.isDirectory();
}
return callback(o);
});
}
};