agentsqripts
Version:
Comprehensive static code analysis toolkit for identifying technical debt, security vulnerabilities, performance issues, and code quality problems
95 lines (85 loc) • 4.88 kB
JavaScript
/**
* @file Directory processing utility for recursive file analysis and batch operations
* @description Single responsibility: Recursively process files in directory trees with robust error handling
*
* This utility provides systematic directory traversal and file processing capabilities that
* enable batch analysis operations across entire project codebases. It implements recursive
* directory walking with error handling, file filtering, and progress tracking to support
* large-scale analysis workflows while maintaining performance and reliability.
*
* Design rationale:
* - Recursive traversal enables comprehensive codebase analysis across nested directory structures
* - Error isolation prevents individual file failures from stopping entire analysis operations
* - File filtering supports targeted analysis of specific file types and patterns
* - Progress tracking enables user feedback and operation monitoring for large codebases
* - Memory-efficient implementation supports analysis of large directory trees
*
* Directory processing capabilities:
* - Recursive directory tree traversal with configurable depth limits
* - File type filtering based on extensions and naming patterns
* - Individual file processing with comprehensive error handling and recovery
* - Progress tracking and reporting for long-running analysis operations
* - Batch operation optimization for efficient large-scale codebase analysis
*/
const qerrors = require('qerrors'); // Error logging utility
const fs = require('fs').promises; // File system promises API
const path = require('path'); // Path utilities
/**
* Walk directory recursively to process files
* @param {string} currentPath - Directory currently being walked
* @param {string} rootPath - Root directory for relative paths
* @param {Array<string>} extensions - File extensions to include
* @param {Array<string>} excludePatterns - Patterns to exclude
* @param {Function} processFile - File processor callback
* @param {Array} results - Accumulator for processed results
* @returns {Promise<void>} Completion signal
* @throws {Error} Propagates read or processing errors
*/
async function walkDirectory(currentPath, rootPath, extensions, excludePatterns, processFile, results) {
try {
console.log(`walkDirectory: scanning ${currentPath}`); // Log start of directory scan
const entries = await fs.readdir(currentPath, { withFileTypes: true }); // Read directory entries
for (const entry of entries) { // Iterate over each directory entry
const fullPath = path.join(currentPath, entry.name); // Build absolute path to entry
const relativePath = path.relative(rootPath, fullPath); // Compute path relative to root
if (excludePatterns.some(pattern => relativePath.includes(pattern))) { // Skip excluded patterns
continue; // Continue to next entry if pattern matched
}
if (entry.isDirectory()) { // Recurse into subdirectory
await walkDirectory(fullPath, rootPath, extensions, excludePatterns, processFile, results); // Process subdirectory
} else if (entry.isFile()) { // Handle file entries
const ext = path.extname(entry.name).toLowerCase(); // Extract file extension
if (extensions.includes(ext)) { // Check extension against allowed list
const result = await processFile(fullPath, relativePath); // Execute provided file processor
if (result) results.push(result); // Collect result when available
}
}
}
console.log(`walkDirectory: finished ${currentPath}`); // Log completion of directory scan
} catch (error) {
qerrors.default(error, 'walkDirectory failed', { currentPath }); // Report error with context
throw error; // Propagate error for upstream handling
}
}
/**
* Process files in directory
* @param {string} dirPath - Directory path
* @param {Array<string>} extensions - File extensions
* @param {Array<string>} excludePatterns - Patterns to exclude
* @param {Function} processFile - File processor function
* @returns {Promise<Array>} Processed results
* @throws {Error} Propagates directory walking errors
*/
async function processDirectory(dirPath, extensions, excludePatterns, processFile) {
const results = []; // Initialize results container
try {
console.log(`processDirectory: start ${dirPath}`); // Log start of processing
await walkDirectory(dirPath, dirPath, extensions, excludePatterns, processFile, results); // Begin recursive walk
console.log(`processDirectory: complete ${dirPath}`); // Log end of processing
return results; // Return accumulated results
} catch (error) {
qerrors.default(error, 'processDirectory failed', { dirPath }); // Report error with context
throw error; // Propagate error to caller
}
}
module.exports = { processDirectory, walkDirectory }; // Export utilities