chromancer
Version:
A powerful command-line interface for automating Chrome browser using Playwright. Perfect for web scraping, automation, testing, and browser workflows.
130 lines (129 loc) ⢠5.16 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DataFormatter = void 0;
const tslib_1 = require("tslib");
const fs = tslib_1.__importStar(require("node:fs/promises"));
const path = tslib_1.__importStar(require("node:path"));
class DataFormatter {
static async saveAndDisplay(data, options = {}) {
const { format = 'json', filename, directory, display = true, useGlobalDir = true } = options;
// Determine directory - use global ~/.chromancer/data by default
const dir = directory || (useGlobalDir
? path.join(process.env.HOME || process.env.USERPROFILE || '', '.chromancer', 'data')
: path.join(process.cwd(), 'tmp'));
// Ensure directory exists
await fs.mkdir(dir, { recursive: true });
// Generate filename if not provided
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const finalFilename = filename || `chromancer-data-${timestamp}.${format}`;
const filepath = path.join(dir, finalFilename);
// Format data based on type
let formatted;
let displayText;
switch (format) {
case 'json':
formatted = JSON.stringify(data, null, 2);
displayText = this.formatForDisplay(data);
break;
case 'csv':
formatted = this.toCSV(data);
displayText = formatted;
break;
case 'text':
formatted = this.toText(data);
displayText = formatted;
break;
default:
formatted = JSON.stringify(data, null, 2);
displayText = this.formatForDisplay(data);
}
// Save to file
await fs.writeFile(filepath, formatted);
// Display if requested
if (display) {
console.log('\nš Data extracted:');
console.log('ā'.repeat(60));
console.log(displayText);
console.log('ā'.repeat(60));
// Show user-friendly path
const home = process.env.HOME || process.env.USERPROFILE || '';
const displayPath = filepath.startsWith(home)
? filepath.replace(home, '~')
: filepath;
console.log(`\nš¾ Data saved to: ${displayPath}`);
}
return { filepath, displayed: displayText };
}
static formatForDisplay(data) {
// If it's a string, return as-is
if (typeof data === 'string') {
return data;
}
// If it's an array, show count and first few items
if (Array.isArray(data)) {
const preview = data.slice(0, 5);
let display = `Array with ${data.length} items:\n`;
preview.forEach((item, index) => {
if (typeof item === 'object') {
display += `\n[${index}] ${JSON.stringify(item, null, 2)}`;
}
else {
display += `\n[${index}] ${item}`;
}
});
if (data.length > 5) {
display += `\n\n... and ${data.length - 5} more items`;
}
return display;
}
// For objects, show formatted JSON
return JSON.stringify(data, null, 2);
}
static toCSV(data) {
if (!Array.isArray(data)) {
throw new Error('CSV format requires array data');
}
if (data.length === 0) {
return '';
}
// Handle array of objects
if (typeof data[0] === 'object' && data[0] !== null) {
const headers = Object.keys(data[0]);
const csvHeaders = headers.join(',');
const csvRows = data.map(row => headers.map(header => {
const value = row[header];
// Escape quotes and wrap in quotes if contains comma
const escaped = String(value).replace(/"/g, '""');
return escaped.includes(',') ? `"${escaped}"` : escaped;
}).join(','));
return [csvHeaders, ...csvRows].join('\n');
}
// Handle array of primitives
return data.map(item => String(item)).join('\n');
}
static toText(data) {
if (typeof data === 'string') {
return data;
}
if (Array.isArray(data)) {
return data.map((item, index) => {
if (typeof item === 'object') {
return `--- Item ${index + 1} ---\n${JSON.stringify(item, null, 2)}`;
}
return `${index + 1}. ${item}`;
}).join('\n\n');
}
return JSON.stringify(data, null, 2);
}
static detectFormat(instruction) {
const lower = instruction.toLowerCase();
if (lower.includes('csv') || lower.includes('spreadsheet') || lower.includes('excel')) {
return 'csv';
}
if (lower.includes('text') || lower.includes('plain') || lower.includes('list')) {
return 'text';
}
return 'json';
}
}
exports.DataFormatter = DataFormatter;