sfcoe-ailabs
Version:
AI-powered code review tool with static analysis integration for comprehensive code quality assessment.
88 lines (87 loc) • 3.3 kB
JavaScript
import path from 'node:path';
import fs from 'fs';
import { Logger } from '../../utils/observability.js';
import { COMMAND_DEFAULTS } from '../../utils/constants.js';
import SCATProvider from './scatProvider.js';
export default class SFCodeAnalyzer extends SCATProvider {
/**
* Creates a new Salesforce Code Analyzer instance
*
* @param scanDirectory - The directory to scan for Salesforce code
* @param configFile - Optional configuration file path for the analyzer
*/
constructor(scanDirectory, configFile) {
const sarifFileName = path.join(scanDirectory, COMMAND_DEFAULTS.DEFAULT_SARIF_FILE_NAME);
super(scanDirectory, configFile ?? '', sarifFileName);
}
/**
* Runs the Salesforce Code Analyzer on the specified directory
*
* @param scanDirectory - Optional override for the scan directory
* @returns Promise that resolves to the SARIF analysis results
*/
async run(scanDirectory) {
const directoryToScan = scanDirectory ?? this.getScanDirectory();
const { execa: execaModule } = await import('execa');
// Create log directory if it doesn't exist
await this.ensureLogDirectoryExists();
// Build v5.x command arguments
const args = [
'code-analyzer',
'run',
'--workspace',
directoryToScan,
'--target',
directoryToScan,
'--output-file',
this.getSarifFileName(),
'--rule-selector',
'all',
];
// Add config file if provided
if (this.getConfigFile()) {
args.push('--config-file', this.getConfigFile());
}
Logger.debug(`Running SF code analyzer command for Salesforce files: \n sf ${args.join(' ')}`);
try {
await execaModule('sf', args, {
cwd: directoryToScan,
stdio: 'inherit',
});
}
catch (error) {
Logger.error('Code Analyzer execution failed:', error);
throw error;
}
return this.getSarifFile();
}
/**
* Ensures the log directory exists.
* Creates the directory if it doesn't exist.
*
* @returns Promise that resolves when directory is ensured to exist
*/
async ensureLogDirectoryExists() {
try {
const configFile = this.getConfigFile();
let logDir;
if (configFile) {
// Get the directory containing the config file
const configDir = path.dirname(configFile);
// The log folder is 'code-analyzer-logs' relative to the config file directory
logDir = path.join(configDir, COMMAND_DEFAULTS.SF_CODE_ANALYZER_LOGS_FOLDER);
}
else {
// Default to creating the log directory in the scan directory
logDir = path.join(this.getScanDirectory(), COMMAND_DEFAULTS.SF_CODE_ANALYZER_LOGS_FOLDER);
}
// Create the directory if it doesn't exist
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir);
}
}
catch (error) {
Logger.warn('Warning: Could not create log directory:', error);
}
}
}