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
943 lines ⢠36.2 kB
JavaScript
;
/**
* CLI Output Manager - Handle file output, formatting, and user feedback
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.OutputManager = void 0;
const fs_1 = require("fs");
const path_1 = require("path");
const version_1 = require("../utils/version");
const overview_1 = require("../analyzers/overview");
const quality_1 = require("../analyzers/quality");
class OutputManager {
options;
combinedSections = [];
combineMode = false;
constructor(options) {
this.options = options;
}
/**
* Output Section 1 results in the specified format
*/
outputSection1(result, filename) {
const formatter = new overview_1.Section1Formatter();
const outputFiles = [];
// Generate content based on format
let content;
let extension;
switch (this.options.output) {
case 'json':
content = this.formatAsJSON(result);
extension = '.json';
break;
case 'yaml':
content = this.formatAsYAML(result);
extension = '.yaml';
break;
case 'txt':
content = formatter.formatReport(result);
extension = '.txt';
break;
case 'markdown':
default:
content = formatter.formatReport(result);
extension = '.md';
break;
}
// In combine mode, just collect the content
if (this.combineMode && (this.options.output === 'markdown' || this.options.output === 'txt')) {
this.addToCombinedOutput(content);
return outputFiles;
}
// Output to file or stdout
if (this.options.outputFile) {
const outputPath = this.ensureExtension(this.options.outputFile, extension);
this.writeToFile(outputPath, content);
outputFiles.push(outputPath);
}
else if (filename) {
// Auto-generate filename based on input
const outputPath = this.generateOutputFilename(filename, extension);
this.writeToFile(outputPath, content);
outputFiles.push(outputPath);
}
else {
// Output to stdout
console.log(content);
}
// Also generate summary if verbose and not quiet
if (this.options.verbose && !this.options.quiet) {
const summary = formatter.formatSummary(result);
console.log('\nš Quick Summary:');
console.log(summary);
}
return outputFiles;
}
/**
* Output Section 2 (Data Quality) results in the specified format
*/
outputSection2(result, filename) {
const outputFiles = [];
// Generate content based on format
let content;
let extension;
switch (this.options.output) {
case 'json':
content = this.formatSection2AsJSON(result);
extension = '.json';
break;
case 'yaml':
content = this.formatSection2AsYAML(result);
extension = '.yaml';
break;
case 'txt':
content = quality_1.Section2Formatter.formatReport(result.qualityAudit);
extension = '.txt';
break;
case 'markdown':
default:
content = quality_1.Section2Formatter.formatReport(result.qualityAudit);
extension = '.md';
break;
}
// In combine mode, just collect the content
if (this.combineMode && (this.options.output === 'markdown' || this.options.output === 'txt')) {
this.addToCombinedOutput(content);
return outputFiles;
}
// Output to file or stdout
if (this.options.outputFile) {
const outputPath = this.ensureExtension(this.options.outputFile, extension);
this.writeToFile(outputPath, content);
outputFiles.push(outputPath);
}
else if (filename) {
// Auto-generate filename based on input
const outputPath = this.generateSection2OutputFilename(filename, extension);
this.writeToFile(outputPath, content);
outputFiles.push(outputPath);
}
else {
// Output to stdout
console.log(content);
}
// Also generate summary if verbose and not quiet
if (this.options.verbose && !this.options.quiet) {
const cockpit = result.qualityAudit.cockpit;
console.log('\nš§ Data Quality Summary:');
console.log(` Overall Score: ${cockpit.compositeScore.score.toFixed(1)}/100`);
console.log(` Interpretation: ${cockpit.compositeScore.interpretation}`);
}
return outputFiles;
}
/**
* Output Section 3 (EDA) results in the specified format
*/
outputSection3(section3Report, result, filename) {
const outputFiles = [];
// Generate content based on format
let content;
let extension;
switch (this.options.output) {
case 'json':
content = this.formatSection3AsJSON(result);
extension = '.json';
break;
case 'yaml':
content = this.formatSection3AsYAML(result);
extension = '.yaml';
break;
case 'txt':
content = section3Report;
extension = '.txt';
break;
case 'markdown':
default:
content = section3Report;
extension = '.md';
break;
}
// In combine mode, just collect the content
if (this.combineMode && (this.options.output === 'markdown' || this.options.output === 'txt')) {
this.addToCombinedOutput(content);
return outputFiles;
}
// Output to file or stdout
if (this.options.outputFile) {
const outputPath = this.ensureExtension(this.options.outputFile, extension);
this.writeToFile(outputPath, content);
outputFiles.push(outputPath);
}
else if (filename) {
// Auto-generate filename based on input
const outputPath = this.generateSection3OutputFilename(filename, extension);
this.writeToFile(outputPath, content);
outputFiles.push(outputPath);
}
else {
// Output to stdout
console.log(content);
}
// Also generate summary if verbose and not quiet
if (this.options.verbose && !this.options.quiet) {
const insights = result.edaAnalysis?.crossVariableInsights;
if (insights?.topFindings && insights.topFindings.length > 0) {
console.log('\nš EDA Quick Summary:');
insights.topFindings.slice(0, 3).forEach((finding, i) => {
console.log(` ${i + 1}. ${finding}`);
});
}
}
return outputFiles;
}
/**
* Output Section 4 (Visualization Intelligence) results in the specified format
*/
outputSection4(section4Report, result, filename) {
const outputFiles = [];
// Generate content based on format
let content;
let extension;
switch (this.options.output) {
case 'json':
content = this.formatSection4AsJSON(result);
extension = '.json';
break;
case 'yaml':
content = this.formatSection4AsYAML(result);
extension = '.yaml';
break;
case 'txt':
content = section4Report;
extension = '.txt';
break;
case 'markdown':
default:
content = section4Report;
extension = '.md';
break;
}
// In combine mode, just collect the content
if (this.combineMode && (this.options.output === 'markdown' || this.options.output === 'txt')) {
this.addToCombinedOutput(content);
return outputFiles;
}
// Output to file or stdout
if (this.options.outputFile) {
const outputPath = this.ensureExtension(this.options.outputFile, extension);
this.writeToFile(outputPath, content);
outputFiles.push(outputPath);
}
else if (filename) {
// Auto-generate filename based on input
const outputPath = this.generateSection4OutputFilename(filename, extension);
this.writeToFile(outputPath, content);
outputFiles.push(outputPath);
}
else {
// Output to stdout
console.log(content);
}
// Also generate summary if verbose and not quiet
if (this.options.verbose && !this.options.quiet) {
const recommendations = result.performanceMetrics?.recommendationsGenerated || 0;
const chartTypes = result.performanceMetrics?.chartTypesConsidered || 0;
const confidence = result.metadata?.recommendationConfidence || 0;
console.log('\nš Visualization Intelligence Quick Summary:');
console.log(` ⢠Generated ${recommendations} chart recommendations across ${chartTypes} types`);
console.log(` ⢠Overall confidence: ${(confidence * 100).toFixed(0)}%`);
console.log(` ⢠Accessibility: WCAG 2.1 AA Ready`);
if (result.warnings && result.warnings.length > 0) {
const criticalWarnings = result.warnings.filter((w) => w.severity === 'critical' || w.severity === 'high');
if (criticalWarnings.length > 0) {
console.log(` ā ļø ${criticalWarnings.length} critical considerations identified`);
}
}
}
return outputFiles;
}
/**
* Output Section 5 (Data Engineering) results in the specified format
*/
outputSection5(section5Report, result, filename) {
const outputFiles = [];
// Generate content based on format
let content;
let extension;
switch (this.options.output) {
case 'json':
content = this.formatSection5AsJSON(result);
extension = '.json';
break;
case 'yaml':
content = this.formatSection5AsYAML(result);
extension = '.yaml';
break;
case 'txt':
content = section5Report;
extension = '.txt';
break;
case 'markdown':
default:
content = section5Report;
extension = '.md';
break;
}
// In combine mode, just collect the content
if (this.combineMode && (this.options.output === 'markdown' || this.options.output === 'txt')) {
this.addToCombinedOutput(content);
return outputFiles;
}
// Output to file or stdout
if (this.options.outputFile) {
const outputPath = this.ensureExtension(this.options.outputFile, extension);
this.writeToFile(outputPath, content);
outputFiles.push(outputPath);
}
else if (filename) {
// Auto-generate filename based on input
const outputPath = this.generateSection5OutputFilename(filename, extension);
this.writeToFile(outputPath, content);
outputFiles.push(outputPath);
}
else {
// Output to stdout
console.log(content);
}
// Also generate summary if verbose and not quiet
if (this.options.verbose && !this.options.quiet) {
const mlReadiness = result.metadata?.mlReadinessScore || 0;
const transformations = result.performanceMetrics?.transformationsEvaluated || 0;
console.log('\nšļø Data Engineering Quick Summary:');
console.log(` ⢠ML Readiness Score: ${mlReadiness}%`);
console.log(` ⢠Transformations Evaluated: ${transformations}`);
console.log(` ⢠Schema Optimization: Ready for ${result.engineeringAnalysis?.schemaAnalysis?.optimizedSchema?.targetSystem || 'generic SQL'}`);
}
return outputFiles;
}
/**
* Output Section 6 (Predictive Modeling) results in the specified format
*/
outputSection6(section6Report, result, filename) {
const outputFiles = [];
// Generate content based on format
let content;
let extension;
switch (this.options.output) {
case 'json':
content = this.formatSection6AsJSON(result);
extension = '.json';
break;
case 'yaml':
content = this.formatSection6AsYAML(result);
extension = '.yaml';
break;
case 'txt':
content = section6Report;
extension = '.txt';
break;
case 'markdown':
default:
content = section6Report;
extension = '.md';
break;
}
// In combine mode, just collect the content
if (this.combineMode && (this.options.output === 'markdown' || this.options.output === 'txt')) {
this.addToCombinedOutput(content);
return outputFiles;
}
// Output to file or stdout
if (this.options.outputFile) {
const outputPath = this.ensureExtension(this.options.outputFile, extension);
this.writeToFile(outputPath, content);
outputFiles.push(outputPath);
}
else if (filename) {
// Auto-generate filename based on input
const outputPath = this.generateSection6OutputFilename(filename, extension);
this.writeToFile(outputPath, content);
outputFiles.push(outputPath);
}
else {
// Output to stdout
console.log(content);
}
// Also generate summary if verbose and not quiet
if (this.options.verbose && !this.options.quiet) {
const tasksIdentified = result.performanceMetrics?.tasksIdentified || 0;
const algorithmsEvaluated = result.performanceMetrics?.algorithmsEvaluated || 0;
console.log('\nš§ Modeling Analysis Quick Summary:');
console.log(` ⢠Tasks Identified: ${tasksIdentified}`);
console.log(` ⢠Algorithms Evaluated: ${algorithmsEvaluated}`);
console.log(` ⢠Ethics Assessment: Complete with bias analysis`);
}
return outputFiles;
}
/**
* Output Join Analysis results in the specified format
*/
outputJoinAnalysis(joinReport, result, filename) {
const outputFiles = [];
// Generate content based on format
let content;
let extension;
switch (this.options.output) {
case 'json':
content = this.formatJoinAsJSON(result);
extension = '.json';
break;
case 'yaml':
content = this.formatJoinAsYAML(result);
extension = '.yaml';
break;
case 'txt':
content = joinReport;
extension = '.txt';
break;
case 'markdown':
default:
content = joinReport;
extension = '.md';
break;
}
// In combine mode, just collect the content
if (this.combineMode && (this.options.output === 'markdown' || this.options.output === 'txt')) {
this.addToCombinedOutput(content);
return outputFiles;
}
// Output to file or stdout
if (this.options.outputFile) {
const outputPath = this.ensureExtension(this.options.outputFile, extension);
this.writeToFile(outputPath, content);
outputFiles.push(outputPath);
}
else if (filename) {
// Auto-generate filename based on input
const outputPath = this.generateJoinOutputFilename(filename, extension);
this.writeToFile(outputPath, content);
outputFiles.push(outputPath);
}
else {
// Output to stdout
console.log(content);
}
// Also generate summary if verbose and not quiet
if (this.options.verbose && !this.options.quiet) {
const summary = result.summary;
console.log('\nš Join Analysis Quick Summary:');
console.log(` ⢠Tables Analyzed: ${summary?.tablesAnalyzed || 0}`);
console.log(` ⢠Join Candidates Found: ${summary?.joinCandidatesFound || 0}`);
console.log(` ⢠High Confidence Joins: ${summary?.highConfidenceJoins || 0}`);
console.log(` ⢠Analysis Time: ${summary?.analysisTime || 0}ms`);
}
return outputFiles;
}
/**
* Output validation results
*/
outputValidation(filePath, isValid, errors) {
const filename = filePath.split('/').pop() || filePath;
if (isValid) {
console.log(`ā
${filename} is a valid CSV file`);
}
else {
console.log(`ā ${filename} has validation issues:`);
errors.forEach((error) => console.log(` ⢠${error}`));
}
}
/**
* Output file information
*/
outputFileInfo(metadata) {
console.log('š File Information:');
console.log(` ⢠Name: ${metadata.originalFilename}`);
console.log(` ⢠Size: ${this.formatFileSize(metadata.fileSizeMB)}`);
console.log(` ⢠Encoding: ${metadata.encoding || 'auto-detected'}`);
console.log(` ⢠Format: ${metadata.mimeType}`);
console.log(` ⢠Modified: ${metadata.lastModified?.toISOString?.() || 'unknown'}`);
}
/**
* Format as JSON with pretty printing
*/
formatAsJSON(result) {
// Create a clean object for JSON output
const jsonOutput = {
metadata: {
version: (0, version_1.getDataPilotVersion)(),
generatedAt: new Date().toISOString(),
command: 'datapilot',
},
overview: result.overview,
warnings: result.warnings,
performance: result.performanceMetrics,
};
return JSON.stringify(jsonOutput, null, 2);
}
/**
* Format as YAML (simplified implementation)
*/
formatAsYAML(result) {
// Simple YAML formatting - in production you might want to use a proper YAML library
// Include any additional properties that might be added to the result (for testing purposes)
const additionalProps = {};
for (const [key, value] of Object.entries(result)) {
if (!['overview', 'warnings', 'performanceMetrics'].includes(key)) {
additionalProps[key] = value;
}
}
const yaml = this.objectToYAML({
metadata: {
version: (0, version_1.getDataPilotVersion)(),
generatedAt: new Date().toISOString(),
command: 'datapilot',
},
overview: result.overview,
warnings: result.warnings,
performance: result.performanceMetrics,
...additionalProps,
});
return yaml;
}
/**
* Simple object to YAML converter
*/
objectToYAML(obj, indent = 0, seen = new WeakSet()) {
const spaces = ' '.repeat(indent);
let yaml = '';
for (const [key, value] of Object.entries(obj)) {
// Skip undefined values entirely
if (value === undefined) {
continue;
}
yaml += `${spaces}${key}:`;
if (value === null) {
yaml += ' null\n';
}
else if (typeof value === 'string') {
// Escape quotes, backslashes, and newlines in strings
const escapedValue = value.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\r/g, '\\r');
yaml += ` "${escapedValue}"\n`;
}
else if (typeof value === 'number' || typeof value === 'boolean') {
yaml += ` ${value}\n`;
}
else if (value instanceof Date) {
yaml += ` "${value.toISOString()}"\n`;
}
else if (Array.isArray(value)) {
if (value.length === 0) {
yaml += ' []\n';
}
else {
yaml += '\n';
value.forEach((item) => {
if (item === undefined) {
return; // Skip undefined array items
}
if (typeof item === 'object' && item !== null) {
if (seen.has(item)) {
yaml += `${spaces} - "[Circular Reference]"\n`;
}
else {
seen.add(item);
yaml += `${spaces} -\n${this.objectToYAML(item, indent + 2, seen)}`;
seen.delete(item);
}
}
else if (typeof item === 'string') {
const escapedItem = item.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\r/g, '\\r');
yaml += `${spaces} - "${escapedItem}"\n`;
}
else {
yaml += `${spaces} - ${item}\n`;
}
});
}
}
else if (typeof value === 'object') {
// Check for circular references
if (seen.has(value)) {
yaml += ' "[Circular Reference]"\n';
}
else {
seen.add(value);
yaml += '\n';
yaml += this.objectToYAML(value, indent + 1, seen);
seen.delete(value);
}
}
}
// Minimal cleanup: only remove trailing whitespace, preserve structure
return yaml.replace(/[ \t]+$/gm, '');
}
/**
* Format Section 2 result as JSON
*/
formatSection2AsJSON(result) {
const jsonOutput = {
metadata: {
version: (0, version_1.getDataPilotVersion)(),
generatedAt: new Date().toISOString(),
command: 'datapilot quality',
analysisType: 'Data Quality & Integrity Audit',
},
qualityAudit: result.qualityAudit,
warnings: result.warnings,
performanceMetrics: result.performanceMetrics,
};
return JSON.stringify(jsonOutput, null, 2);
}
/**
* Format Section 2 result as YAML
*/
formatSection2AsYAML(result) {
const yaml = this.objectToYAML({
metadata: {
version: (0, version_1.getDataPilotVersion)(),
generatedAt: new Date().toISOString(),
command: 'datapilot quality',
analysisType: 'Data Quality & Integrity Audit',
},
qualityAudit: result.qualityAudit,
warnings: result.warnings,
performanceMetrics: result.performanceMetrics,
});
return yaml;
}
/**
* Format Section 3 result as JSON
*/
formatSection3AsJSON(result) {
const jsonOutput = {
metadata: {
version: (0, version_1.getDataPilotVersion)(),
generatedAt: new Date().toISOString(),
command: 'datapilot eda',
analysisType: 'Exploratory Data Analysis',
},
edaAnalysis: result.edaAnalysis,
warnings: result.warnings,
performanceMetrics: result.performanceMetrics,
analysisMetadata: result.metadata,
};
return JSON.stringify(jsonOutput, null, 2);
}
/**
* Format Section 3 result as YAML
*/
formatSection3AsYAML(result) {
const yaml = this.objectToYAML({
metadata: {
version: (0, version_1.getDataPilotVersion)(),
generatedAt: new Date().toISOString(),
command: 'datapilot eda',
analysisType: 'Exploratory Data Analysis',
},
edaAnalysis: result.edaAnalysis,
warnings: result.warnings,
performanceMetrics: result.performanceMetrics,
analysisMetadata: result.metadata,
});
return yaml;
}
/**
* Format Section 4 result as JSON
*/
formatSection4AsJSON(result) {
const jsonOutput = {
metadata: {
version: (0, version_1.getDataPilotVersion)(),
generatedAt: new Date().toISOString(),
command: 'datapilot viz',
analysisType: 'Visualization Intelligence',
},
visualizationAnalysis: result.visualizationAnalysis,
warnings: result.warnings,
performanceMetrics: result.performanceMetrics,
analysisMetadata: result.metadata,
};
return JSON.stringify(jsonOutput, null, 2);
}
/**
* Format Section 4 result as YAML
*/
formatSection4AsYAML(result) {
const yaml = this.objectToYAML({
metadata: {
version: (0, version_1.getDataPilotVersion)(),
generatedAt: new Date().toISOString(),
command: 'datapilot viz',
analysisType: 'Visualization Intelligence',
},
visualizationAnalysis: result.visualizationAnalysis,
warnings: result.warnings,
performanceMetrics: result.performanceMetrics,
analysisMetadata: result.metadata,
});
return yaml;
}
/**
* Format Section 5 result as JSON
*/
formatSection5AsJSON(result) {
const jsonOutput = {
metadata: {
version: (0, version_1.getDataPilotVersion)(),
generatedAt: new Date().toISOString(),
command: 'datapilot engineering',
analysisType: 'Data Engineering & Structural Insights',
},
engineeringAnalysis: result.engineeringAnalysis,
warnings: result.warnings,
performanceMetrics: result.performanceMetrics,
analysisMetadata: result.metadata,
};
return JSON.stringify(jsonOutput, null, 2);
}
/**
* Format Section 5 result as YAML
*/
formatSection5AsYAML(result) {
const yaml = this.objectToYAML({
metadata: {
version: (0, version_1.getDataPilotVersion)(),
generatedAt: new Date().toISOString(),
command: 'datapilot engineering',
analysisType: 'Data Engineering & Structural Insights',
},
engineeringAnalysis: result.engineeringAnalysis,
warnings: result.warnings,
performanceMetrics: result.performanceMetrics,
analysisMetadata: result.metadata,
});
return yaml;
}
/**
* Format Section 6 result as JSON
*/
formatSection6AsJSON(result) {
const jsonOutput = {
metadata: {
version: (0, version_1.getDataPilotVersion)(),
generatedAt: new Date().toISOString(),
command: 'datapilot modeling',
analysisType: 'Predictive Modeling & Advanced Analytics Guidance',
},
modelingAnalysis: result.modelingAnalysis,
warnings: result.warnings,
performanceMetrics: result.performanceMetrics,
analysisMetadata: result.metadata,
};
return JSON.stringify(jsonOutput, null, 2);
}
/**
* Format Section 6 result as YAML
*/
formatSection6AsYAML(result) {
const yaml = this.objectToYAML({
metadata: {
version: (0, version_1.getDataPilotVersion)(),
generatedAt: new Date().toISOString(),
command: 'datapilot modeling',
analysisType: 'Predictive Modeling & Advanced Analytics Guidance',
},
modelingAnalysis: result.modelingAnalysis,
warnings: result.warnings,
performanceMetrics: result.performanceMetrics,
analysisMetadata: result.metadata,
});
return yaml;
}
/**
* Generate Section 2 output filename
*/
generateSection2OutputFilename(inputFilename, extension) {
const baseName = inputFilename.replace(/\.[^/.]+$/, ''); // Remove extension
return `${baseName}_datapilot_quality${extension}`;
}
/**
* Generate Section 3 output filename
*/
generateSection3OutputFilename(inputFilename, extension) {
const baseName = inputFilename.replace(/\.[^/.]+$/, ''); // Remove extension
return `${baseName}_datapilot_eda${extension}`;
}
/**
* Generate Section 4 output filename
*/
generateSection4OutputFilename(inputFilename, extension) {
const baseName = inputFilename.replace(/\.[^/.]+$/, ''); // Remove extension
return `${baseName}_datapilot_viz${extension}`;
}
/**
* Generate Section 5 output filename
*/
generateSection5OutputFilename(inputFilename, extension) {
const baseName = inputFilename.replace(/\.[^/.]+$/, ''); // Remove extension
return `${baseName}_datapilot_engineering${extension}`;
}
/**
* Generate Section 6 output filename
*/
generateSection6OutputFilename(inputFilename, extension) {
const baseName = inputFilename.replace(/\.[^/.]+$/, ''); // Remove extension
return `${baseName}_datapilot_modeling${extension}`;
}
/**
* Generate Join Analysis output filename
*/
generateJoinOutputFilename(inputFilename, extension) {
const baseName = inputFilename.replace(/\.[^/.]+$/, ''); // Remove extension
return `${baseName}_datapilot_join_analysis${extension}`;
}
/**
* Format Join Analysis result as JSON
*/
formatJoinAsJSON(result) {
const jsonOutput = {
metadata: {
version: (0, version_1.getDataPilotVersion)(),
generatedAt: new Date().toISOString(),
command: 'datapilot engineering (multi-file)',
analysisType: 'Multi-File Join Analysis',
},
joinAnalysis: result,
};
return JSON.stringify(jsonOutput, null, 2);
}
/**
* Format Join Analysis result as YAML
*/
formatJoinAsYAML(result) {
const yaml = this.objectToYAML({
metadata: {
version: (0, version_1.getDataPilotVersion)(),
generatedAt: new Date().toISOString(),
command: 'datapilot engineering (multi-file)',
analysisType: 'Multi-File Join Analysis',
},
joinAnalysis: result,
});
return yaml;
}
/**
* Write content to file with directory creation
*/
writeToFile(filePath, content) {
try {
// Ensure directory exists
const dir = (0, path_1.dirname)(filePath);
(0, fs_1.mkdirSync)(dir, { recursive: true });
// Write file
(0, fs_1.writeFileSync)(filePath, content, 'utf8');
if (!this.options.quiet) {
console.log(`š Report written to: ${filePath}`);
}
}
catch (error) {
throw new Error(`Failed to write output file: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
/**
* Ensure file has the correct extension
*/
ensureExtension(filePath, expectedExtension) {
const currentExtension = (0, path_1.extname)(filePath);
if (currentExtension === expectedExtension) {
return filePath;
}
// If no extension, add the expected one
if (!currentExtension) {
return filePath + expectedExtension;
}
// Replace existing extension with expected one
return filePath.slice(0, -currentExtension.length) + expectedExtension;
}
/**
* Generate output filename based on input filename
*/
generateOutputFilename(inputFilename, extension) {
const baseName = inputFilename.replace(/\.[^/.]+$/, ''); // Remove extension
return `${baseName}_datapilot_report${extension}`;
}
/**
* Format file size for display
*/
formatFileSize(sizeMB) {
if (sizeMB === undefined || sizeMB === null) {
return 'unknown';
}
if (sizeMB < 0.01) {
return `${(sizeMB * 1024).toFixed(1)} KB`;
}
else if (sizeMB >= 1024) {
return `${(sizeMB / 1024).toFixed(2)} GB`;
}
else {
return `${sizeMB.toFixed(2)} MB`;
}
}
/**
* Start collecting sections for combined output
*/
startCombinedOutput() {
this.combinedSections = [];
this.combineMode = true;
}
/**
* Add a section to the combined output
*/
addToCombinedOutput(content) {
this.combinedSections.push(content);
}
/**
* Output the combined sections as a single file
*/
outputCombined(filename) {
if (this.combinedSections.length === 0) {
return [];
}
const outputFiles = [];
const combinedContent = this.combinedSections.join('\n\n---\n\n');
const extension = this.options.output === 'txt' ? '.txt' : '.md';
if (this.options.outputFile) {
const outputPath = this.ensureExtension(this.options.outputFile, extension);
this.writeToFile(outputPath, combinedContent);
outputFiles.push(outputPath);
}
else if (filename) {
const outputPath = this.generateCombinedOutputFilename(filename, extension);
this.writeToFile(outputPath, combinedContent);
outputFiles.push(outputPath);
}
else {
console.log(combinedContent);
}
// Clear combined sections after output
this.combinedSections = [];
this.combineMode = false;
return outputFiles;
}
/**
* Generate combined output filename
*/
generateCombinedOutputFilename(inputFilename, extension) {
const baseName = inputFilename.replace(/\.[^/.]+$/, ''); // Remove extension
const filename = `${baseName}_datapilot_full_report${extension}`;
console.log(`Generated combined output filename: ${filename}`);
return filename;
}
/**
* Show available output formats
*/
static showFormats() {
console.log('š Available output formats:');
console.log(' ⢠markdown (default) - Human-readable report with full details');
console.log(' ⢠json - Machine-readable structured data');
console.log(' ⢠yaml - Human and machine-readable structured data');
console.log('\nExample: datapilot all data.csv --output json --output-file report.json');
}
}
exports.OutputManager = OutputManager;
//# sourceMappingURL=output-manager.js.map