UNPKG

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
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);