dll-cli
Version:
A CLI tool for Digital Law Lab providing necessary DA package management functionalities for testing (i.e. pushing to Docassemble's playground) and other purposes
132 lines (131 loc) • 5.56 kB
JavaScript
import { lstat, readdir } from 'node:fs/promises';
import path from 'node:path';
export const getDirectories = async (source, includeFiles = false, withFileTypes = false) => {
if ((await lstat(source)).isFile())
return [];
try {
return (await readdir(source, { withFileTypes: true }))
.filter((dirent) => !includeFiles
? dirent.isDirectory()
: dirent.isFile() || dirent.isDirectory())
.map((dirent) => (withFileTypes ? dirent : dirent.name));
}
catch (error) {
console.error(error);
return [];
}
};
export const getDirectoriesRecursive = async (source, options, foundDirList = [], remainingDirsToSearch = [], rootPath, level = 1) => {
try {
options = Object.assign({
type: 'directory',
baseOnly: false,
depthLimit: 3,
excludePath: (_nodePath) => _nodePath.includes('node_modules') || _nodePath.includes('.git'),
includeCurrentDir: false,
currentDirText: '.',
}, options);
if (!rootPath)
rootPath = source;
const showFiles = options.type == 'file' || options.type == 'both';
const dontShowDirectories = options.type == 'file';
const getCurrentDirectoryToScan = (_directoryList) => {
let _dirPath, _isDirectory, _depth;
if (typeof _directoryList[0] === 'string') {
_dirPath = path.join(source, _directoryList[0]);
_isDirectory = undefined;
_depth = undefined;
}
if (typeof _directoryList[0] === 'object') {
_dirPath =
'name' in _directoryList[0]
? path.join(source, _directoryList[0].name)
: path.join(rootPath, _directoryList[0].path);
_isDirectory =
'name' in _directoryList[0]
? _directoryList[0].isDirectory()
: _directoryList[0].isDirectory;
_depth = !('name' in _directoryList[0])
? _directoryList[0].path.split(path.sep).length == 0
? 1
: _directoryList[0].path.split(path.sep).length
: undefined;
}
return {
path: path.relative(rootPath, _dirPath),
isDirectory: _isDirectory,
level: _depth + 1,
};
};
const getFoundDirList = () => {
let _dirList = !options.baseOnly
? foundDirList
: foundDirList.map((_path) => path.basename(_path));
if (options.includeCurrentDir)
_dirList = [options.currentDirText, ..._dirList];
return Promise.resolve(_dirList);
};
let dirs = await getDirectories(source, showFiles, showFiles);
if (options.depthLimit === level) {
foundDirList = [
...foundDirList,
...dirs
.map((base) => path.relative(rootPath, path.join(source, showFiles ? base.name : base)))
.filter((_path) => !options.excludePath(_path)),
];
dirs = [];
}
while (dirs.length !== 0 &&
options.excludePath(getCurrentDirectoryToScan(dirs).path)) {
dirs.shift();
}
if (dirs.length === 0 && remainingDirsToSearch.length === 0)
return getFoundDirList();
const currentDirList = dirs.length === 0 ? remainingDirsToSearch : dirs;
let currentDirToScan = getCurrentDirectoryToScan(currentDirList);
if (dirs.length !== 0) {
level += 1;
}
else {
level = currentDirToScan.level;
}
const subPath = path.join(rootPath, currentDirToScan.path);
foundDirList = [
...foundDirList,
...(dontShowDirectories && showFiles && currentDirToScan.isDirectory
? []
: [currentDirToScan.path]),
];
if (dirs.length === 0) {
remainingDirsToSearch = remainingDirsToSearch.slice(1);
}
else {
remainingDirsToSearch = [
...dirs
.slice(1)
.map((base) => ({
path: path.relative(rootPath, path.join(source, showFiles ? base.name : base)),
isDirectory: showFiles ? base.isDirectory() : undefined,
}))
.filter((_dir) => !options.excludePath(_dir.path)),
...remainingDirsToSearch,
];
}
return await getDirectoriesRecursive(subPath, options, foundDirList, remainingDirsToSearch, rootPath, level);
}
catch (error) {
console.log(error);
return [];
}
};
let alreadyVisitedSource, cachedDirs;
export const getCurrentDirsOnce = async (source, options) => {
if (alreadyVisitedSource != source) {
alreadyVisitedSource = source;
cachedDirs = await getDirectoriesRecursive(source, options);
}
return Promise.resolve(cachedDirs);
};
export const delay = (duration = 1000) => new Promise((resolve) => setTimeout(resolve, duration));
export const isEmpty = (_value) => !_value || /^\s*$/.test(_value);
export const containsWhitespace = (_value) => /\s+/.test(_value);