UNPKG

chromancer

Version:

A powerful command-line interface for automating Chrome browser using Playwright. Perfect for web scraping, automation, testing, and browser workflows.

223 lines (219 loc) 8.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const core_1 = require("@oclif/core"); const base_js_1 = require("../base.js"); const fs = tslib_1.__importStar(require("fs/promises")); const path = tslib_1.__importStar(require("path")); const os = tslib_1.__importStar(require("os")); const chalk = { green: (s) => `\x1b[32m${s}\x1b[0m`, blue: (s) => `\x1b[34m${s}\x1b[0m`, yellow: (s) => `\x1b[33m${s}\x1b[0m`, cyan: (s) => `\x1b[36m${s}\x1b[0m`, gray: (s) => `\x1b[90m${s}\x1b[0m`, bold: (s) => `\x1b[1m${s}\x1b[0m`, }; class Init extends base_js_1.BaseCommand { static description = 'Interactive setup wizard - checks Chrome connectivity, creates configuration files, and generates example workflows to get started quickly'; static examples = [ '<%= config.bin %> <%= command.id %>', '<%= config.bin %> <%= command.id %> --skip-chrome-check', '<%= config.bin %> <%= command.id %> --example-workflows', ]; static flags = { 'skip-chrome-check': core_1.Flags.boolean({ description: 'Skip Chrome connectivity check', default: false, }), 'example-workflows': core_1.Flags.boolean({ description: 'Create example workflow files', default: false, }), 'config-only': core_1.Flags.boolean({ description: 'Only create config file', default: false, }), }; async run() { const { flags } = await this.parse(Init); this.showWelcome(); // Step 1: Check Chrome if (!flags['skip-chrome-check'] && !flags['config-only']) { await this.checkChrome(); } // Step 2: Create config await this.createConfig(); // Step 3: Create examples if requested if (flags['example-workflows']) { await this.createExamples(); } // Step 4: Show next steps this.showNextSteps(); } showWelcome() { console.log(); console.log(chalk.bold(chalk.cyan('🧙 Welcome to Chromancer!'))); console.log(chalk.gray('The magical Chrome automation tool')); console.log(); console.log('This wizard will help you:'); console.log(' • Check Chrome connectivity'); console.log(' • Create a configuration file'); console.log(' • Set up example workflows'); console.log(); } async checkChrome() { this.log(chalk.blue('📡 Checking Chrome connectivity...')); try { // Try default port await this.connectToChrome(9222, 'localhost', false); this.log(chalk.green('✅ Chrome is running and accessible on port 9222')); } catch (error) { this.log(chalk.yellow('⚠️ Chrome is not running or not accessible')); this.log(); this.log('To start Chrome with remote debugging:'); this.log(); this.log(chalk.gray(' # Option 1: Use chromancer')); this.log(' chromancer spawn --headless'); this.log(); this.log(chalk.gray(' # Option 2: Start Chrome manually')); this.log(' chrome --remote-debugging-port=9222'); this.log(); this.log(chalk.gray(' # Option 3: Use Docker')); this.log(' docker run -d -p 9222:9222 zenika/alpine-chrome \\'); this.log(' --no-sandbox --remote-debugging-host=0.0.0.0 --remote-debugging-port=9222'); this.log(); } } async createConfig() { const configPath = path.join(os.homedir(), '.chromancer.json'); // Check if config exists try { await fs.access(configPath); this.log(chalk.yellow(`⚠️ Config file already exists: ${configPath}`)); return; } catch { // File doesn't exist, create it } const defaultConfig = { chrome: { port: 9222, host: 'localhost', defaultTimeout: 30000, }, commands: { screenshot: { path: './screenshots', fullPage: true, }, pdf: { path: './pdfs', format: 'A4', }, export: { path: './exports', }, }, workflows: { continueOnError: false, variablePrefix: '${', variableSuffix: '}', }, ui: { colorOutput: true, verboseErrors: true, showTips: true, }, }; await fs.writeFile(configPath, JSON.stringify(defaultConfig, null, 2)); this.log(chalk.green(`✅ Created config file: ${configPath}`)); this.log(chalk.gray(' You can edit this file to customize chromancer behavior')); } async createExamples() { const examplesDir = path.join(process.cwd(), 'chromancer-examples'); try { await fs.mkdir(examplesDir, { recursive: true }); } catch (error) { this.warn('Could not create examples directory'); return; } // Create a simple example const simpleExample = `# Simple workflow example # Run with: chromancer run simple.yml - navigate: https://example.com - wait: selector: h1 timeout: 5000 - screenshot: example-home.png - click: a[href*="more"] - wait: time: 2000 - screenshot: example-more.png `; await fs.writeFile(path.join(examplesDir, 'simple.yml'), simpleExample); // Create a form example const formExample = `# Form automation example # Run with: chromancer run form.yml --var EMAIL=test@example.com - navigate: https://example.com/contact - wait: selector: form - fill: form: name: "Test User" email: \${EMAIL} message: "This is an automated test" - screenshot: form-filled.png # Uncomment to submit: # - click: button[type="submit"] `; await fs.writeFile(path.join(examplesDir, 'form.yml'), formExample); // Create a scraping example const scrapingExample = `# Web scraping example # Run with: chromancer run scraping.yml - navigate: https://news.ycombinator.com - wait: selector: .itemlist - evaluate: | // Extract top stories Array.from(document.querySelectorAll('.athing')).slice(0, 10).map(item => ({ title: item.querySelector('.titleline a')?.textContent, link: item.querySelector('.titleline a')?.href, rank: item.querySelector('.rank')?.textContent })) - export: format: json output: hn-stories.json `; await fs.writeFile(path.join(examplesDir, 'scraping.yml'), scrapingExample); this.log(chalk.green(`✅ Created example workflows in: ${examplesDir}`)); this.log(chalk.gray(' • simple.yml - Basic navigation')); this.log(chalk.gray(' • form.yml - Form automation')); this.log(chalk.gray(' • scraping.yml - Data extraction')); } showNextSteps() { console.log(); console.log(chalk.bold(chalk.green('🎉 Setup complete!'))); console.log(); console.log('Next steps:'); console.log(); console.log('1. Start Chrome (if not running):'); console.log(chalk.cyan(' chromancer spawn')); console.log(); console.log('2. Try a simple command:'); console.log(chalk.cyan(' chromancer navigate https://example.com')); console.log(chalk.cyan(' chromancer screenshot example.png')); console.log(); console.log('3. Run a workflow:'); console.log(chalk.cyan(' chromancer run chromancer-examples/simple.yml')); console.log(); console.log('4. Explore more commands:'); console.log(chalk.cyan(' chromancer --help')); console.log(); console.log(chalk.gray('📚 Full documentation: https://chromancer.dev')); console.log(); } } exports.default = Init;