This repository has been archived by the owner on Jun 15, 2020. It is now read-only.
/
directory.ts
78 lines (75 loc) · 3.01 KB
/
directory.ts
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
import { readdir, stat } from 'fs';
import { Entry } from './entry';
import { file as parse } from './file';
import { resolve as resolvePath, parse as parsePath } from 'path';
import { fileExtensions } from './file-extensions';
const objectValues = require('object-values');
const ignoreDirectoryList = ['node_modules'];
type DirectoryOptions = {
basedir?: string;
};
export async function directory(path: string, options: DirectoryOptions = {}): Promise<Entry[]> {
try {
var dirpath = resolvePath(options.basedir || '.', path); // eslint-disable-line tslint/config
} catch (err) {
return Promise.reject(err);
}
return new Promise<string[]>((done, reject) => {
readdir(dirpath, (err, files) => {
if (err) {
return reject(err);
}
done(files);
});
}).then((items: string[]) => {
const directories: string[] = [];
let count = items.length;
if (count === 0) {
return Promise.resolve([]);
}
return new Promise<{ directories: string[]; files: string[] }>((done, reject) => {
const names: { [name: string]: [number, string] } = Object.create(null);
items.forEach(item => {
stat(resolvePath(dirpath, item), (err, stats) => {
if (err) {
return reject(err);
}
if (stats.isDirectory()) {
if (!ignoreDirectoryList.includes(item)) {
directories.push(item);
}
} else if (stats.isFile()) {
const { name, ext } = parsePath(item);
const extIndex = fileExtensions.indexOf(ext);
if (extIndex !== - 1) {
const [nameIndex] = names[name] || [Infinity];
if (extIndex < nameIndex) {
names[name] = [extIndex, item];
}
}
}
count = count - 1;
if (count === 0) {
done({ directories, files: objectValues(names).map(([, file]) => file) });
}
});
});
}).then(({ directories, files }) => {
const result: Entry[] = [];
const options = { basedir: dirpath };
const promises = files.map(file => parse(file, options)
.then(entries => {
result.push(...entries);
}));
return Promise.all(promises)
.then(async () => {
const promises = directories.map(async (d) => {
return directory(d, options).then(entries => {
result.push(...entries);
});
});
return Promise.all(promises).then(() => result);
});
});
});
}