#!/usr/bin/env node import { Command } from 'commander'; import dotenv from 'dotenv'; import path from 'path'; import { OpticparseClient, ScrapeRequest } from './index'; // Load default environment variables from the current working directory's .env file dotenv.config(); const program = new Command(); program .name('opticparse') .description('Command-line utility to scrape dynamic web pages using AI Vision & Gemini.') .version('1.0.0'); program .command('scrape') .description('Execute a visual scrape operation against a webpage.') .requiredOption('-u, --url ', 'The URL of the webpage to scrape.') .requiredOption('-q, --query ', 'The structured query explaining what JSON data to extract.') .option('-k, --key ', 'API key credential. Falls back to OPTICPARSE_API_KEY env variable.') .option('-a, --api-url ', 'Custom target API server host URL.') .option('--width ', 'Browser viewport width.', '1280') .option('--height ', 'Browser viewport height.', '800') .option('--wait-until ', 'Playwright wait criteria: networkidle, load, or domcontentloaded.', 'networkidle') .option('-t, --timeout ', 'Scraper connection & execution timeout in milliseconds.', '90000') .action(async (options) => { try { const apiKey = options.key || process.env.OPTICPARSE_API_KEY; const apiUrl = options.apiUrl || process.env.OPTICPARSE_API_URL; if (!apiKey) { console.error('\x1b[31mError: API Key is missing.\x1b[0m'); console.error('Please specify the key using the -k/--key flag, or set the OPTICPARSE_API_KEY environment variable.'); process.exit(1); } const client = new OpticparseClient({ apiKey, apiUrl, }); const scrapeRequest: ScrapeRequest = { targetUrl: options.url, extractionQuery: options.query, viewportWidth: parseInt(options.width, 10), viewportHeight: parseInt(options.height, 10), waitUntil: options.waitUntil as any, timeout: parseInt(options.timeout, 10), }; console.log(`\x1b[36mInitiating visual scraping of:\x1b[0m ${options.url}`); console.log(`\x1b[36mQuery:\x1b[0m "${options.query}"`); const startTime = Date.now(); const result = await client.scrape(scrapeRequest); const duration = ((Date.now() - startTime) / 1000).toFixed(2); console.log(`\x1b[32mSuccessfully scraped in ${duration}s!\x1b[0m`); console.log('\n\x1b[35m=== Extracted JSON Result ===\x1b[0m'); console.log(JSON.stringify(result, null, 2)); console.log('\x1b[35m=============================\x1b[0m'); } catch (error: any) { console.error('\n\x1b[31m=== Scraper Execution Failed ===\x1b[0m'); console.error(`\x1b[31mMessage:\x1b[0m ${error.message}`); if (error.statusCode) { console.error(`\x1b[31mHTTP Status Code:\x1b[0m ${error.statusCode}`); } if (error.details) { console.error(`\x1b[31mServer Details:\x1b[0m ${error.details}`); } console.error('\x1b[31m================================\x1b[0m'); process.exit(1); } }); program.parse(process.argv);