datapilot-cli
Version:
Enterprise-grade streaming multi-format data analysis with comprehensive statistical insights and intelligent relationship detection - supports CSV, JSON, Excel, TSV, Parquet - memory-efficient, cross-platform
257 lines ⢠10.5 kB
JavaScript
;
/**
* DataPilot CLI - Lean Entry Point
* Orchestrates focused modules for comprehensive CSV data analysis
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.DataPilotCLI = void 0;
exports.main = main;
const argument_parser_1 = require("./argument-parser");
const universal_analyzer_1 = require("./universal-analyzer");
const output_manager_1 = require("./output-manager");
const memory_manager_1 = require("../utils/memory-manager");
const logger_1 = require("../utils/logger");
const windows_path_helper_1 = require("./windows-path-helper");
class DataPilotCLI {
parser;
analyzer;
outputManager;
constructor() {
this.parser = new argument_parser_1.ArgumentParser();
this.analyzer = new universal_analyzer_1.UniversalAnalyzer();
this.outputManager = new output_manager_1.OutputManager({});
this.initializeGlobalHandlers();
}
/**
* Main CLI execution entry point
*/
async run(argv = process.argv) {
try {
// Parse command line arguments
const context = this.parser.parse(argv);
if (context.command === 'version') {
console.log(this.parser.getVersion());
return { success: true, exitCode: 0 };
}
if (!context.file && (!context.args || context.args.length === 0)) {
this.parser.showHelp();
return {
success: false,
exitCode: 1,
data: { error: 'No input files specified' }
};
}
// Detect multi-file scenarios for engineering command
const isMultiFileEngineering = context.command === 'engineering' && context.args && context.args.length > 1;
// Add command to options for proper section selection
const analysisOptions = {
...context.options,
command: context.command
};
// Run analysis - route to appropriate analyzer method
let result;
if (context.command === 'all') {
this.outputManager.startCombinedOutput();
}
if (isMultiFileEngineering) {
// Multi-file join analysis
result = await this.analyzer.analyzeMultipleFiles(context.args, analysisOptions);
}
else {
// Single file analysis (existing behavior)
const filePath = context.file || context.args[0];
result = await this.analyzer.analyzeFile(filePath, analysisOptions);
}
// If analysis was successful, format and output the results
if (result.success && result.data) {
const primaryFilePath = isMultiFileEngineering ? context.args[0] : (context.file || context.args[0]);
await this.formatAndOutputResults(result, primaryFilePath, context.options);
if (context.command === 'all') {
this.outputManager.outputCombined(primaryFilePath);
}
}
return result;
}
catch (error) {
logger_1.logger.error(`CLI execution failed: ${error}`);
return {
success: false,
exitCode: 1,
data: { error: String(error) }
};
}
finally {
// Ensure cleanup runs
await this.cleanup();
}
}
/**
* Format and output analysis results using OutputManager
*/
async formatAndOutputResults(result, filePath, options) {
try {
// Update the output manager with current options
this.outputManager = new output_manager_1.OutputManager(options);
const analysisData = result.data;
const fileName = filePath.split('/').pop() || filePath;
// Output each section that was analyzed
if (analysisData.section1) {
this.outputManager.outputSection1(analysisData.section1, fileName);
}
if (analysisData.section2) {
this.outputManager.outputSection2(analysisData.section2, fileName);
}
if (analysisData.section3) {
// Generate report content for Section 3
const section3Report = this.generateSection3Report(analysisData.section3);
this.outputManager.outputSection3(section3Report, analysisData.section3, fileName);
}
if (analysisData.section4) {
// Generate report content for Section 4
const section4Report = this.generateSection4Report(analysisData.section4);
this.outputManager.outputSection4(section4Report, analysisData.section4, fileName);
}
if (analysisData.section5) {
// Generate report content for Section 5
const section5Report = this.generateSection5Report(analysisData.section5);
this.outputManager.outputSection5(section5Report, analysisData.section5, fileName);
}
if (analysisData.section6) {
// Generate report content for Section 6
const section6Report = this.generateSection6Report(analysisData.section6);
this.outputManager.outputSection6(section6Report, analysisData.section6, fileName);
}
// Handle join analysis results
if (analysisData.joinAnalysis) {
const joinReport = this.generateJoinAnalysisReport(analysisData.joinAnalysis);
this.outputManager.outputJoinAnalysis(joinReport, analysisData.joinAnalysis, fileName);
}
}
catch (error) {
logger_1.logger.error('Failed to format and output results:', error);
// Fall back to simple output
if (!options.quiet) {
console.log('\nš Analysis Results:');
console.log(JSON.stringify(result.data, null, 2));
}
}
}
/**
* Generate Section 3 report content
*/
generateSection3Report(section3Result) {
const { Section3Formatter } = require('../analyzers/eda');
return Section3Formatter.formatSection3(section3Result);
}
/**
* Generate Section 4 report content
*/
generateSection4Report(section4Result) {
const { Section4Formatter } = require('../analyzers/visualization');
return Section4Formatter.formatSection4(section4Result);
}
/**
* Generate Section 5 report content
*/
generateSection5Report(section5Result) {
const { Section5Formatter } = require('../analyzers/engineering');
return Section5Formatter.formatMarkdown(section5Result);
}
/**
* Generate Section 6 report content
*/
generateSection6Report(section6Result) {
const { Section6Formatter } = require('../analyzers/modeling');
return Section6Formatter.formatMarkdown(section6Result);
}
/**
* Generate Join Analysis report content
*/
generateJoinAnalysisReport(joinResult) {
const { JoinFormatter } = require('../analyzers/joins');
const formatter = new JoinFormatter();
return formatter.format(joinResult, { type: 'MARKDOWN' });
}
/**
* Set progress callback for test purposes
*/
setProgressCallback(callback) {
// This could be implemented by passing callback to command executor
// For now, this is a placeholder for compatibility
}
/**
* Initialize global error handling and memory management
*/
initializeGlobalHandlers() {
// Start memory monitoring
memory_manager_1.globalMemoryManager.startMonitoring({ analyzer: 'CLI', operation: 'initialization' });
// Register global cleanup handler
memory_manager_1.globalCleanupHandler.register(async () => {
logger_1.logger.debug('CLI cleanup: stopping memory monitoring');
memory_manager_1.globalMemoryManager.stopMonitoring();
});
// Handle process exit gracefully
process.on('SIGINT', async () => {
logger_1.logger.info('Received SIGINT, cleaning up...');
await this.cleanup();
process.exit(0);
});
process.on('SIGTERM', async () => {
logger_1.logger.info('Received SIGTERM, cleaning up...');
await this.cleanup();
process.exit(0);
});
}
/**
* Cleanup resources
*/
async cleanup() {
try {
memory_manager_1.globalMemoryManager.stopMonitoring();
await memory_manager_1.globalCleanupHandler.runCleanup();
}
catch (error) {
logger_1.logger.error('Cleanup failed:', error);
}
}
}
exports.DataPilotCLI = DataPilotCLI;
// Main execution when run directly
async function main() {
try {
// Check for Windows-specific help flag
if (process.argv.includes('--help-windows')) {
windows_path_helper_1.WindowsPathHelper.showWindowsHelp();
return;
}
// Proactive Windows installation health check
if (windows_path_helper_1.WindowsPathHelper.isWindows()) {
// Only check if this looks like the first run or if there might be issues
const hasMinimalArgs = process.argv.length <= 2 || process.argv.includes('--version');
const hasHelpFlag = process.argv.includes('--help') || process.argv.includes('-h');
if (hasMinimalArgs || hasHelpFlag) {
windows_path_helper_1.WindowsPathHelper.checkInstallationHealth();
}
}
const cli = new DataPilotCLI();
const result = await cli.run();
// Exit with appropriate code
process.exit(result.exitCode || (result.success ? 0 : 1));
}
catch (error) {
console.error('Fatal CLI error:', error);
// Provide Windows-specific guidance if this looks like a PATH issue
windows_path_helper_1.WindowsPathHelper.provideErrorGuidance(error);
process.exit(1);
}
}
// Execute main function if this file is run directly
if (require.main === module) {
main().catch((error) => {
console.error('Unhandled CLI error:', error);
process.exit(1);
});
}
exports.default = DataPilotCLI;
//# sourceMappingURL=index.js.map