UNPKG

chromancer

Version:

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

198 lines (197 loc) • 7.75 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const core_1 = require("@oclif/core"); const base_js_1 = require("../base.js"); const selectors_js_1 = require("../utils/selectors.js"); const evaluation_js_1 = require("../utils/evaluation.js"); class Store extends base_js_1.BaseCommand { static description = 'Store values from page elements or evaluations for later use'; static examples = [ '<%= config.bin %> <%= command.id %> --selector "#price" --as "originalPrice"', '<%= config.bin %> <%= command.id %> --eval "document.title" --as "pageTitle"', '<%= config.bin %> <%= command.id %> --selector "#username" --as "username" --property "value"', '<%= config.bin %> <%= command.id %> --cookies --as "sessionCookies"', '<%= config.bin %> <%= command.id %> --list', '<%= config.bin %> <%= command.id %> --clear', ]; static flags = { ...base_js_1.BaseCommand.baseFlags, selector: core_1.Flags.string({ char: 's', description: 'CSS selector of element to store value from', exclusive: ['eval', 'list', 'clear', 'cookies'], }), eval: core_1.Flags.string({ char: 'e', description: 'JavaScript expression to evaluate and store', exclusive: ['selector', 'list', 'clear', 'cookies'], }), cookies: core_1.Flags.boolean({ description: 'Store all cookies', exclusive: ['selector', 'eval', 'list', 'clear'], }), as: core_1.Flags.string({ char: 'a', description: 'Variable name to store the value as', dependsOn: ['selector', 'eval', 'cookies'], }), property: core_1.Flags.string({ char: 'p', description: 'Element property to store (default: textContent)', default: 'textContent', dependsOn: ['selector'], }), attribute: core_1.Flags.string({ description: 'Element attribute to store', exclusive: ['property'], dependsOn: ['selector'], }), list: core_1.Flags.boolean({ description: 'List all stored values', exclusive: ['selector', 'eval', 'clear', 'cookies'], }), clear: core_1.Flags.boolean({ description: 'Clear all stored values', exclusive: ['selector', 'eval', 'list', 'cookies'], }), json: core_1.Flags.boolean({ description: 'Output stored values as JSON', dependsOn: ['list'], }), }; // Static storage that persists across command invocations static storage = {}; async run() { const { flags } = await this.parse(Store); // Handle list and clear operations without Chrome connection if (flags.list) { this.listStoredValues(flags.json); return; } if (flags.clear) { this.clearStoredValues(); return; } // For other operations, connect to Chrome await this.connectToChrome(flags.port, flags.host, flags.launch, flags.profile, flags.headless, flags.verbose, flags.keepOpen); if (!this.page) { this.error('Failed to connect to Chrome'); } await this.executeCommand(this.page, flags); } async executeCommand(page, flags) { // Ensure chromancer namespace exists in the page await page.evaluate(` if (typeof window.chromancer === 'undefined') { window.chromancer = { stored: {} }; } else if (typeof window.chromancer.stored === 'undefined') { window.chromancer.stored = {}; } `); // Inject existing stored values into the page for (const [key, value] of Object.entries(Store.storage)) { await page.evaluate(` window.chromancer.stored["${key}"] = ${JSON.stringify(value)}; `); } let value; if (flags.selector) { // Store from element try { this.log(`šŸ” Looking for element: ${flags.selector}`); const element = await (0, selectors_js_1.waitForElement)(page, flags.selector, { timeout: 5000, state: 'attached' }); if (flags.attribute) { // Get attribute value value = await element.getAttribute(flags.attribute); this.logVerbose(`Getting attribute "${flags.attribute}"`); } else { // Get property value value = await element.evaluate((el, prop) => { return el[prop]; }, flags.property); this.logVerbose(`Getting property "${flags.property}"`); } } catch (error) { if (error.name === 'TimeoutError') { this.error(`Element not found: ${flags.selector}`); } throw error; } } else if (flags.eval) { // Store from evaluation this.log(`šŸ”§ Evaluating expression...`); value = await (0, evaluation_js_1.safeEvaluate)(page, flags.eval); } else if (flags.cookies) { // Store cookies this.log(`šŸŖ Getting cookies...`); value = await page.context().cookies(); } if (!flags.as) { this.error('Variable name required. Use --as flag to specify a name'); } // Store the value Store.storage[flags.as] = value; // Also store in the page context await page.evaluate(` window.chromancer.stored["${flags.as}"] = ${JSON.stringify(value)}; `); this.log(`āœ… Stored value as "${flags.as}": ${this.formatValue(value)}`); // Log storage info if verbose if (flags.verbose) { this.logVerbose('Storage info', { variable: flags.as, type: typeof value, isArray: Array.isArray(value), totalStored: Object.keys(Store.storage).length, }); } } formatValue(value) { if (typeof value === 'string') { return value.length > 100 ? `"${value.substring(0, 100)}..."` : `"${value}"`; } if (typeof value === 'object') { const str = JSON.stringify(value); return str.length > 100 ? str.substring(0, 100) + '...' : str; } return String(value); } listStoredValues(json = false) { if (Object.keys(Store.storage).length === 0) { this.log('āŒ No values stored'); return; } if (json) { // Output as JSON for scripting console.log(JSON.stringify(Store.storage, null, 2)); } else { this.log('šŸ“¦ Stored values:'); for (const [key, value] of Object.entries(Store.storage)) { this.log(` ${key}: ${this.formatValue(value)}`); } this.log(`\nšŸ“Š Total: ${Object.keys(Store.storage).length} value(s)`); } } clearStoredValues() { const count = Object.keys(Store.storage).length; Store.storage = {}; this.log(`āœ… Cleared all stored values (${count} values removed)`); } // Public method to access storage from other commands static getStoredValue(key) { return Store.storage[key]; } // Public method to get all stored values static getAllStoredValues() { return { ...Store.storage }; } } exports.default = Store;