|
/* eslint-env node */ |
|
|
|
const path = require('path'); |
|
const fs = require('fs'); |
|
const util = require('util'); |
|
const readdir = util.promisify(fs.readdir); |
|
const fstat = util.promisify(fs.fstat); |
|
const open = util.promisify(fs.open); |
|
|
|
/** |
|
* @param {string} dir |
|
* @returns {Promise<boolean>} |
|
*/ |
|
async function isDir(dir) { |
|
try { |
|
const fd = await open(dir, 'r'); |
|
const stat = await fstat(fd); |
|
|
|
return stat.isDirectory(); |
|
} catch (ex) { |
|
return false; |
|
} |
|
} |
|
|
|
/** |
|
* @param {string} file |
|
* @returns {Promise<boolean>} |
|
*/ |
|
async function isFile(file) { |
|
try { |
|
const fd = await open(file, 'r'); |
|
const stat = await fstat(fd); |
|
|
|
return stat.isFile(); |
|
} catch (ex) { |
|
return false; |
|
} |
|
} |
|
|
|
/** |
|
* @param {array} dirs |
|
* @returns {array} |
|
*/ |
|
function hasResult(dirs) { |
|
return dirs.filter((dir) => dir); |
|
} |
|
|
|
/** |
|
* @param {string} baseDir |
|
* @param {function} matcher |
|
* @param {string|string[]} [extraPath] |
|
* @returns {Function} |
|
*/ |
|
function getCheck(baseDir, matcher, extraPath = []) { |
|
return function(checkedEntry) { |
|
return matcher( |
|
path.join.apply(path, [baseDir, checkedEntry].concat(extraPath)) |
|
).then((result) => result && checkedEntry); |
|
}; |
|
} |
|
|
|
/** |
|
* @param {string} baseDir |
|
* @param {array} entries |
|
* @param {function} matcher |
|
* @param {string|string[]} [extraPath] |
|
* @returns {Promise<string[]>} |
|
*/ |
|
function checkAll(baseDir, entries, matcher, extraPath) { |
|
return Promise.all( |
|
entries.map(getCheck(baseDir, matcher, extraPath)) |
|
).then(hasResult); |
|
} |
|
|
|
/** |
|
* @param {string} baseDir |
|
* @param {string} indexFile |
|
* @param {object} hashmap |
|
* @param {string} dir |
|
* @returns {object} |
|
*/ |
|
function toConfig(baseDir, indexFile, hashmap, dir) { |
|
return { |
|
...hashmap, |
|
[dir]: path.join(baseDir, dir, indexFile) |
|
}; |
|
} |
|
|
|
/** |
|
* @param {string} baseDir |
|
* @param {string} [indexFile='index.js'] |
|
* @returns {Promise<string[]>} |
|
*/ |
|
exports.getEntries = async function(baseDir, indexFile = 'index.js') { |
|
const dirContent = await readdir(baseDir); |
|
|
|
return checkAll(baseDir, dirContent, isDir) |
|
.then((dirs) => checkAll(baseDir, dirs, isFile, indexFile)) |
|
.then((dirs) => dirs.reduce(toConfig.bind(null, baseDir, indexFile), {})); |
|
}; |