UNPKG

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

344 lines • 13 kB
"use strict"; /** * Interactive prompts for DataPilot CLI * Provides user-friendly prompts for missing arguments and confirmations */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.InteractivePrompt = void 0; const fs_1 = require("fs"); const path_1 = require("path"); const readline = __importStar(require("readline")); class InteractivePrompt { rl; constructor() { this.rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: true, }); } /** * Prompt for CSV file selection */ async promptForFile(currentDir = process.cwd()) { console.log('\nšŸ“‚ Select a CSV file to analyze:\n'); // List CSV files in current directory const csvFiles = this.findCSVFiles(currentDir); if (csvFiles.length > 0) { console.log('Found CSV files in current directory:'); csvFiles.forEach((file, index) => { const stats = (0, fs_1.statSync)((0, path_1.join)(currentDir, file)); const size = this.formatFileSize(stats.size); console.log(` ${index + 1}. ${file} (${size})`); }); console.log(` ${csvFiles.length + 1}. Enter custom path`); console.log(''); const choice = await this.prompt({ type: 'input', message: 'Enter number or file path:', validate: (input) => { const inputStr = String(input); const num = parseInt(inputStr, 10); if (!isNaN(num) && num >= 1 && num <= csvFiles.length + 1) { return true; } if ((0, fs_1.existsSync)(inputStr)) { return true; } return 'Please enter a valid number or file path'; }, }); const num = parseInt(String(choice), 10); if (!isNaN(num) && num <= csvFiles.length) { return (0, path_1.join)(currentDir, csvFiles[num - 1]); } else if (num === csvFiles.length + 1) { return this.promptForCustomPath(); } return String(choice); } else { console.log('No CSV files found in current directory.'); return this.promptForCustomPath(); } } /** * Prompt for custom file path */ async promptForCustomPath() { return this.prompt({ type: 'input', message: 'Enter CSV file path:', validate: (input) => { const inputStr = String(input); if (!inputStr) return 'File path is required'; if (!(0, fs_1.existsSync)(inputStr)) return 'File not found'; if (!inputStr.toLowerCase().endsWith('.csv')) return 'File must be a CSV'; return true; }, }); } /** * Prompt for command selection */ async promptForCommand() { const commands = [ { name: 'all - Complete analysis (all 6 sections)', value: 'all' }, { name: 'overview - Dataset overview (Section 1)', value: 'overview' }, { name: 'quality - Data quality audit (Section 2)', value: 'quality' }, { name: 'eda - Exploratory data analysis (Section 3)', value: 'eda' }, { name: 'viz - Visualization recommendations (Section 4)', value: 'viz' }, { name: 'engineering - Data engineering insights (Section 5)', value: 'engineering' }, { name: 'modeling - Predictive modeling guidance (Section 6)', value: 'modeling' }, { name: 'validate - Quick validation only', value: 'validate' }, { name: 'info - File information', value: 'info' }, ]; console.log('\nšŸ“Š Select analysis type:\n'); commands.forEach((cmd, index) => { console.log(` ${index + 1}. ${cmd.name}`); }); console.log(''); const choice = await this.prompt({ type: 'input', message: 'Enter number (1-9):', default: '1', validate: (input) => { const num = parseInt(String(input), 10); return (num >= 1 && num <= commands.length) || 'Please enter a valid number'; }, }); return commands[parseInt(String(choice), 10) - 1].value; } /** * Prompt for output format */ async promptForOutputFormat() { const formats = [ { name: 'Text (.txt) - Plain text report', value: 'txt' }, { name: 'Markdown (.md) - Formatted report', value: 'markdown' }, { name: 'JSON - Machine-readable data', value: 'json' }, { name: 'YAML - Human-readable data', value: 'yaml' }, ]; console.log('\nšŸ“„ Select output format:\n'); formats.forEach((fmt, index) => { console.log(` ${index + 1}. ${fmt.name}`); }); console.log(''); const choice = await this.prompt({ type: 'input', message: 'Enter number (1-4):', default: '1', validate: (input) => { const num = parseInt(String(input), 10); return (num >= 1 && num <= formats.length) || 'Please enter a valid number'; }, }); return formats[parseInt(String(choice), 10) - 1].value; } /** * Confirm processing of large file */ async confirmLargeFile(filePath, size) { const sizeStr = this.formatFileSize(size); console.log(`\nāš ļø Large file detected: ${sizeStr}`); console.log(` File: ${filePath}`); console.log(` Estimated processing time: ${this.estimateProcessingTime(size)}`); console.log(` Recommended memory: ${this.recommendedMemory(size)} MB\n`); return this.prompt({ type: 'confirm', message: 'Continue with processing?', default: false, }); } /** * Prompt for performance options */ async promptForPerformanceOptions(fileSize) { const recommendedChunkSize = Math.min(1000, Math.max(100, Math.floor(fileSize / 1000000))); const recommendedMemory = this.recommendedMemory(fileSize); console.log('\nāš™ļø Performance Options:\n'); const useDefaults = await this.prompt({ type: 'confirm', message: 'Use recommended settings?', default: true, }); if (useDefaults) { return { chunkSize: recommendedChunkSize, maxMemory: recommendedMemory, maxRows: undefined, }; } const chunkSize = await this.prompt({ type: 'input', message: `Chunk size (rows per batch):`, default: recommendedChunkSize.toString(), validate: (input) => { const num = parseInt(String(input), 10); return num > 0 || 'Must be a positive number'; }, }); const maxMemory = await this.prompt({ type: 'input', message: `Memory limit (MB):`, default: recommendedMemory.toString(), validate: (input) => { const num = parseInt(String(input), 10); return num > 0 || 'Must be a positive number'; }, }); const limitRows = await this.prompt({ type: 'confirm', message: 'Limit number of rows to process?', default: false, }); let maxRows; if (limitRows) { maxRows = await this.prompt({ type: 'input', message: 'Maximum rows to process:', default: '100000', validate: (input) => { const num = parseInt(String(input), 10); return num > 0 || 'Must be a positive number'; }, }); } return { chunkSize: parseInt(String(chunkSize), 10), maxMemory: parseInt(String(maxMemory), 10), maxRows: maxRows ? parseInt(String(maxRows), 10) : undefined, }; } /** * Basic prompt implementation */ prompt(options) { return new Promise((resolve) => { let question = options.message; if (options.type === 'confirm') { question += ` (${options.default ? 'Y/n' : 'y/N'}): `; } else if (options.default !== undefined) { question += ` (${options.default}): `; } else { question += ': '; } this.rl.question(question, (answer) => { answer = answer.trim(); // Handle defaults if (!answer && options.default !== undefined) { answer = options.default.toString(); } // Handle confirmation if (options.type === 'confirm') { const confirmed = answer.toLowerCase() === 'y' || (answer === '' && options.default === true); resolve(confirmed); return; } // Validate input if (options.validate) { const validation = options.validate(answer); if (validation !== true) { console.log(`āŒ ${validation}`); this.prompt(options).then(resolve); return; } } resolve(answer); }); }); } /** * Find CSV files in directory */ findCSVFiles(dir) { const fs = require('fs'); try { const files = fs.readdirSync(dir); return files.filter((file) => file.toLowerCase().endsWith('.csv')).sort(); } catch { return []; } } /** * Format file size for display */ formatFileSize(bytes) { if (bytes < 1024) return `${bytes} B`; if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; if (bytes < 1024 * 1024 * 1024) return `${(bytes / 1024 / 1024).toFixed(1)} MB`; return `${(bytes / 1024 / 1024 / 1024).toFixed(2)} GB`; } /** * Estimate processing time based on file size */ estimateProcessingTime(bytes) { // Rough estimation: 10MB/s processing speed const seconds = bytes / (10 * 1024 * 1024); if (seconds < 60) return `${Math.ceil(seconds)} seconds`; if (seconds < 3600) return `${Math.ceil(seconds / 60)} minutes`; return `${(seconds / 3600).toFixed(1)} hours`; } /** * Recommend memory based on file size */ recommendedMemory(bytes) { // Rough estimation: 10% of file size + 100MB overhead const recommended = Math.ceil(bytes / (10 * 1024 * 1024)) + 100; return Math.min(4096, Math.max(256, recommended)); // Between 256MB and 4GB } /** * Cleanup resources */ close() { this.rl.close(); } } exports.InteractivePrompt = InteractivePrompt; // Export for use in CLI exports.default = InteractivePrompt; //# sourceMappingURL=interactive-prompt.js.map