UNPKG

agentsqripts

Version:

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

210 lines (204 loc) 8.32 kB
/** * @file Robust file operation utilities with comprehensive error handling * @description Single responsibility: Provide safe file system operations across AgentSqripts * * This utility module provides robust file system operations with graceful error handling, * consistent return patterns, and performance optimizations. It abstracts Node.js file * system complexity while maintaining reliability for large-scale code analysis operations. * * Design rationale: * - Promise-based API for modern async/await patterns * - Graceful error handling prevents analysis pipeline failures * - Consistent return patterns (null for failures, empty arrays, boolean status) * - UTF-8 encoding standardization for text file operations */ const fs = require('fs'); const { promises: fsPromises } = require('fs'); /** * Read file content with graceful error handling and consistent return pattern * * Technical function: Provides safe file reading with null return for failures * * Implementation rationale: * - Async/await pattern enables clean error handling without callback complexity * - UTF-8 encoding explicitly specified for consistent text handling * - Null return value enables easy failure detection without exception handling * - Warning-level logging preserves error information without stopping execution * * Error handling strategy: * - Catches all file system errors (ENOENT, EACCES, EISDIR, etc.) * - Returns null for consistent failure indication across all error types * - Warning message provides debugging information without breaking analysis flow * - Graceful degradation enables analysis to continue with partial data * * Performance considerations: * - Single fsPromises.readFile call minimizes system call overhead * - UTF-8 encoding specified to avoid default encoding detection overhead * - No additional file stat calls required for basic read operations * - Promise-based operation enables efficient concurrent file reading * * Alternative approaches considered: * - Throwing exceptions: Rejected to maintain analysis pipeline stability * - Synchronous fs.readFileSync: Rejected for blocking behavior * - Streaming for all files: Rejected as overkill for typical analysis file sizes * * @param {string} filePath - Absolute or relative path to file to read * @returns {Promise<string|null>} File content as UTF-8 string, or null if read fails * @example * const content = await readFileSafely('config.js'); * if (content !== null) { * // Process file content * } else { * // Handle missing or inaccessible file * } */ async function readFileSafely(filePath) { try { return await fsPromises.readFile(filePath, 'utf-8'); } catch (error) { console.warn(`Warning: Could not read ${filePath}: ${error.message}`); return null; } } /** * Write file content with comprehensive error handling and success indication * * Technical function: Provides safe file writing with boolean success indication * * Implementation rationale: * - Boolean return value enables simple success/failure checking * - UTF-8 encoding ensures consistent text file output * - Error-level logging for failures (more serious than read failures) * - Atomic write operation using Node.js fsPromises for reliability * * Error handling strategy: * - Catches all write errors (ENOSPC, EACCES, ENOTDIR, etc.) * - Boolean return enables immediate success/failure detection * - Error-level logging appropriate for write failures (data loss risk) * - No partial write state - operation either succeeds completely or fails * * File writing considerations: * - UTF-8 encoding for consistent text output across platforms * - Atomic write operation prevents partial file corruption * - No intermediate temporary files for simplicity * - Directory creation not included - caller responsible for directory existence * * Write operation patterns: * - Analysis report generation to JSON/text files * - Configuration file updates after analysis * - Cache file writing for performance optimization * - Debug output and logging to files * * @param {string} filePath - Target file path for writing content * @param {string} content - String content to write to file * @returns {Promise<boolean>} True if write succeeded, false if write failed * @example * const success = await writeFileSafely('output.json', JSON.stringify(data)); * if (success) { * console.log('Report saved successfully'); * } else { * console.log('Failed to save report'); * } */ async function writeFileSafely(filePath, content) { try { await fsPromises.writeFile(filePath, content, 'utf-8'); return true; } catch (error) { console.error(`Error writing to ${filePath}: ${error.message}`); return false; } } /** * Check file system accessibility with simple boolean result * * Technical function: Tests file/directory accessibility without additional metadata * * Implementation rationale: * - Uses fs.access() for lightweight accessibility testing * - Boolean return simplifies conditional logic in callers * - No error logging (accessibility checks are often exploratory) * - Catches all exceptions to provide clean boolean interface * * Accessibility check use cases: * - Validating input paths before attempting file operations * - Checking configuration file existence before reading * - Verifying output directory accessibility before writing * - Conditional file processing based on availability * * Access check behavior: * - Tests both read and write accessibility by default * - Works for both files and directories * - Respects file system permissions and existence * - No detailed error information (use for simple existence/permission checks) * * Performance optimization: * - Minimal system call overhead with fs.access * - No file content reading or metadata fetching * - Suitable for high-frequency accessibility checks * - Promise-based for efficient batch checking * * @param {string} filePath - File or directory path to check for accessibility * @returns {Promise<boolean>} True if path is accessible, false otherwise * @example * if (await isAccessible('optional-config.js')) { * const config = await readFileSafely('optional-config.js'); * } */ async function isAccessible(filePath) { try { await fsPromises.access(filePath); return true; } catch { return false; } } /** * Get directory entries with comprehensive error handling and metadata * * Technical function: Reads directory contents with file type information * * Implementation rationale: * - withFileTypes option provides Dirent objects with type information * - Empty array return enables consistent iteration regardless of errors * - Warning-level logging for directory access issues * - Promise-based operation for efficient directory traversal * * Directory reading strategy: * - Returns Dirent objects with isFile(), isDirectory() methods * - Empty array return enables safe forEach/map operations * - No recursive traversal (single directory level only) * - File type metadata included for filtering operations * * Error scenarios handled: * - ENOENT: Directory does not exist * - EACCES: Permission denied for directory access * - ENOTDIR: Path exists but is not a directory * - EMFILE: Too many open files (system resource exhaustion) * * Directory traversal patterns: * - Project file discovery for analysis * - Configuration directory scanning * - Output directory validation and preparation * - Recursive directory tree building (as building block) * * @param {string} dirPath - Directory path to read entries from * @returns {Promise<Array<fs.Dirent>>} Array of directory entries with type info, empty if error * @example * const entries = await getDirectoryEntries('./src'); * const jsFiles = entries.filter(entry => entry.isFile() && entry.name.endsWith('.js')); */ async function getDirectoryEntries(dirPath) { try { return await fsPromises.readdir(dirPath, { withFileTypes: true }); } catch (error) { console.warn(`Warning: Cannot access ${dirPath}: ${error.message}`); return []; } } module.exports = { readFileSafely, writeFileSafely, isAccessible, getDirectoryEntries };