als-file-list
Version:
Generates filtered and sorted list of all file paths in a directory and its subdirectories.
89 lines (76 loc) • 3.2 kB
JavaScript
const fs = require('fs');
function checkWhere(where, relativePath, stats, isDir, errors) {
if (where) {
try { if (where(relativePath, stats, isDir) === false) return false }
catch (error) { addError(error, { relativePath, where: where.name }, errors) }
}
return true
}
function sortAndSelect(sort,result,skip,limit,select) {
if(sort) {
sortBy(sort,result)
result = sliceArray(result,skip,limit)
}
if(result.length === 0) return result
else return result.map(({relativePath,stats}) => checkSelect(relativePath,stats,select))
}
function addError(error, details, errors) {
error.details = details
errors.push(error)
}
function notExistsSync() {
if(fs.existsSync(dirPath)) return false
addError(new Error(`${dirPath} not exists`),{dirPath},errors)
return true
}
async function notExists(dirPath,errors) {
try {await fs.promises.access(dirPath)}
catch (error) {
addError(new Error(`${dirPath} not exists`),{dirPath},errors)
return true
}
return false
}
function checkSelect(relativePath,stats,select) {
if(select === undefined) return relativePath
if(select.length === 0) return relativePath
const obj = { relativePath }
select.forEach(key => {
if (stats[key]) obj[key] = stats[key]
});
return obj
}
function sortBy(property, array) {
if (array.length === 0) return;
array.sort((a, b) => {
let valueA = (property === 'relativePath') ? a.relativePath : a.stats[property];
let valueB = (property === 'relativePath') ? b.relativePath : b.stats[property];
if (typeof valueA === 'string' && typeof valueB === 'string') valueA.localeCompare(valueB)
else return valueA - valueB;
});
}
function validate(obj,type,required,allowed = []) {
const [key,value] = Object.entries(obj)[0]
if(required && (obj === undefined || obj === null)) throw new Error(`${key} is required`)
if(!value) return
if(type === 'number' && value < 0) throw new Error(`${key} has to be >= 0`)
if(typeof value !== type) throw new Error(`${key} has to be type of ${type}`)
if(allowed.length && !allowed.includes(value)) throw new Error(`The value can be only one of ${allowed.join()}`)
}
function validateOptions(dirPath,{ level = Infinity, where, select,limit=Infinity,skip=0,sort }) {
validate({dirPath},'string',true)
validate({level},'number',true)
validate({limit},'number',true)
validate({where},'function',false)
validate({select},'string',false)
validate({skip},'number',false)
validate({sort},'string',false)
return { level, where, select,limit,skip,sort}
}
function sliceArray(arr, skip = 0, limit = Infinity) {
// Корректировка skip и limit в соответствии с длиной массива
skip = Math.min(skip, arr.length);
limit = Math.min(limit, arr.length - skip);
return arr.slice(skip, skip + limit); // Возвращаем подмассив, начиная с skip и ограниченный limit
}
module.exports = {checkWhere,validateOptions,addError,notExists,sortAndSelect,notExistsSync}