UNPKG

agentsqripts

Version:

Comprehensive static code analysis toolkit for identifying technical debt, security vulnerabilities, performance issues, and code quality problems

172 lines (154 loc) 6.55 kB
/** * @file Comprehensive file system utilities for robust cross-platform operations * @description Single responsibility: Provide foundational file system operations with error handling and optimization * * This utility module provides essential file system operations that serve as building blocks * for all AgentSqripts analysis tools. It implements recursive directory traversal, path * validation, extension filtering, and pattern exclusion with robust error handling and * performance optimizations for large-scale code analysis workflows. * * Design rationale: * - Centralized file system operations eliminate code duplication across analyzers * - Robust error handling prevents analysis pipeline failures from file system issues * - Performance optimizations support analysis of large codebases efficiently * - Cross-platform compatibility ensures consistent behavior across operating systems * - Configurable filtering enables targeted analysis of specific file types and patterns * * Core capabilities: * - Recursive directory traversal with intelligent exclusion patterns * - Extension-based file filtering for targeted analysis workflows * - Path validation and resolution with comprehensive error checking * - Performance-optimized file discovery for large project analysis * - Platform-independent file system operations with consistent behavior */ const fs = require('fs'); // built-in file system module const path = require('path'); // built-in path module const qerrors = require('qerrors'); // error logging helper /** * Get all files recursively from a directory (async version for better scalability) * @param {string} dir - Directory path * @param {Array<string>} extensions - File extensions to include * @param {Array<string>} excludePatterns - Patterns to exclude * @returns {Promise<Array<string>>} Array of file paths */ async function getAllFiles(dir, extensions = [], excludePatterns = []) { const results = []; // collected file paths await walkDirectoryAsync(dir, extensions, excludePatterns, results); // traverse directory tree return results; // return accumulated results } /** * Determine if a file should be excluded * @param {string} filePath - Path of file to evaluate * @param {Array<string>} excludePatterns - Patterns to match against * @returns {boolean} True if file should be skipped */ function shouldExclude(filePath, excludePatterns = []) { return excludePatterns.some(pattern => filePath.includes(pattern)); // check patterns } /** * Walk a directory tree asynchronously for better scalability * @param {string} currentDir - Directory to walk * @param {Array<string>} extensions - Extensions to include * @param {Array<string>} excludePatterns - Patterns to exclude * @param {Array<string>} results - Accumulator for file paths * @returns {Promise<void>} */ async function walkDirectoryAsync(currentDir, extensions = [], excludePatterns = [], results = []) { try { const { promises: fsPromises } = require('fs'); const files = await fsPromises.readdir(currentDir); // read directory contents async for (const file of files) { const filePath = path.join(currentDir, file); // build full path if (shouldExclude(filePath, excludePatterns)) continue; // skip excluded paths const stat = await fsPromises.stat(filePath); // inspect file stats async if (stat.isDirectory()) { await walkDirectoryAsync(filePath, extensions, excludePatterns, results); // recurse into directory } else if (extensions.length === 0 || extensions.some(ext => file.endsWith(ext))) { results.push(filePath); // store matching file } } } catch (error) { qerrors(error, `Failed to walk directory`, { currentDir }); // log walking errors } } /** * Walk a directory tree synchronously (legacy version for compatibility) * @deprecated Use walkDirectoryAsync for better performance * @param {string} currentDir - Directory to walk * @param {Array<string>} extensions - Extensions to include * @param {Array<string>} excludePatterns - Patterns to exclude * @param {Array<string>} results - Accumulator for file paths * @returns {void} */ function walkDirectorySync(currentDir, extensions = [], excludePatterns = [], results = []) { console.warn(`Warning: walkDirectorySync is deprecated. Use walkDirectoryAsync for better performance.`); try { const files = fs.readdirSync(currentDir); // read directory contents for (const file of files) { const filePath = path.join(currentDir, file); // build full path if (shouldExclude(filePath, excludePatterns)) continue; // skip excluded paths const stat = fs.statSync(filePath); // inspect file stats if (stat.isDirectory()) { walkDirectorySync(filePath, extensions, excludePatterns, results); // recurse into directory } else if (extensions.length === 0 || extensions.some(ext => file.endsWith(ext))) { results.push(filePath); // store matching file } } } catch (error) { qerrors(error, `Failed to walk directory`, { currentDir }); // log walking errors } } /** * Check if path exists (async version for better scalability) * @param {string} filePath - Path to check * @returns {Promise<boolean>} True if path exists */ async function pathExists(filePath) { try { const { promises: fsPromises } = require('fs'); await fsPromises.access(filePath); return true; } catch { return false; } } /** * Check if path exists synchronously (legacy version for compatibility) * @deprecated Use pathExists for better performance * @param {string} filePath - Path to check * @returns {boolean} True if path exists */ function pathExistsSync(filePath) { console.warn(`Warning: pathExistsSync is deprecated. Use pathExists for better performance.`); try { fs.accessSync(filePath); return true; } catch { return false; } } /** * Read file safely (async version for better scalability) * @param {string} filePath - File path * @returns {Promise<string|null>} File content or null if error */ async function readFileSafely(filePath) { try { const { promises: fsPromises } = require('fs'); return await fsPromises.readFile(filePath, 'utf-8'); } catch (error) { console.warn(`Warning: Could not read ${filePath}: ${error.message}`); return null; } } module.exports = { fs, path, getAllFiles, shouldExclude, walkDirectoryAsync, walkDirectorySync, pathExists, pathExistsSync, readFileSafely };