@knowcode/screenshotfetch
Version:
Web application spider with screenshot capture and customer journey documentation. Automate user flow documentation with authentication support.
198 lines (173 loc) ⢠7.75 kB
JavaScript
const { program } = require('commander');
const fs = require('fs').promises;
const path = require('path');
const chalk = require('chalk');
const ScreenshotCapture = require('./capture');
const ApplicationSpider = require('./lib/spider/ApplicationSpider');
program
.name('screenshotfetch')
.description('Web application spider with screenshot capture and customer journey documentation')
.version('1.0.0');
program
.command('capture <url>')
.description('Capture a single screenshot')
.option('-o, --output <path>', 'Output file path', './screenshot.png')
.option('-f, --fullpage', 'Capture full page')
.option('-w, --width <width>', 'Viewport width', '1920')
.option('-h, --height <height>', 'Viewport height', '1080')
.option('-t, --timeout <ms>', 'Navigation timeout', '30000')
.option('-s, --cookie-strategy <strategy>', 'Cookie handling strategy (all|click|remove|block|none)', 'all')
.option('--wait <ms>', 'Wait time after page load', '3000')
.option('--headless <mode>', 'Headless mode (new|false)', 'new')
.action(async (url, options) => {
console.log(chalk.blue('š Starting screenshot capture...'));
const capture = new ScreenshotCapture({
viewport: {
width: parseInt(options.width),
height: parseInt(options.height),
deviceScaleFactor: 1
},
timeout: parseInt(options.timeout),
cookieStrategy: options.cookieStrategy,
waitTime: parseInt(options.wait),
headless: options.headless === 'false' ? false : 'new'
});
try {
await capture.init();
const result = await capture.captureScreenshot(url, options.output, {
fullPage: options.fullpage
});
if (result.success) {
console.log(chalk.green('ā
Screenshot captured successfully!'));
} else {
console.log(chalk.red('ā Failed to capture screenshot:', result.error));
}
} catch (error) {
console.error(chalk.red('Error:', error.message));
} finally {
await capture.close();
}
});
program
.command('batch <file>')
.description('Capture multiple screenshots from a JSON file')
.option('-d, --delay <ms>', 'Delay between captures', '2000')
.option('-s, --cookie-strategy <strategy>', 'Cookie handling strategy (all|click|remove|block|none)', 'all')
.action(async (file, options) => {
console.log(chalk.blue('š Starting batch screenshot capture...'));
try {
const content = await fs.readFile(file, 'utf-8');
const screenshots = JSON.parse(content);
if (!Array.isArray(screenshots)) {
throw new Error('JSON file must contain an array of screenshot configurations');
}
const capture = new ScreenshotCapture({
cookieStrategy: options.cookieStrategy
});
await capture.init();
console.log(chalk.blue(`šø Capturing ${screenshots.length} screenshots...`));
const results = await capture.captureMultiple(screenshots, {
delay: parseInt(options.delay)
});
const successful = results.filter(r => r.success).length;
const failed = results.filter(r => !r.success).length;
console.log(chalk.green(`ā
Successful: ${successful}`));
if (failed > 0) {
console.log(chalk.red(`ā Failed: ${failed}`));
}
await capture.close();
} catch (error) {
console.error(chalk.red('Error:', error.message));
}
});
program
.command('spider <start-url>')
.description('Spider a web application and generate customer journey documentation')
.option('-u, --username <username>', 'Username for authentication')
.option('-p, --password <password>', 'Password for authentication')
.option('-o, --output-dir <dir>', 'Output directory for documentation', './docs')
.option('-d, --max-depth <depth>', 'Maximum crawl depth per flow', '10')
.option('--max-flows <flows>', 'Maximum number of flows to discover', '5')
.option('--max-pages <pages>', 'Maximum total pages to visit', '100')
.option('--include-query-params', 'Include query parameters in URLs', true)
.option('--flow-mode', 'Focus on customer journey flows', true)
.option('-w, --width <width>', 'Viewport width', '1920')
.option('-h, --height <height>', 'Viewport height', '1080')
.option('--wait <ms>', 'Wait time between actions', '2000')
.option('--headless <mode>', 'Headless mode (new|false)', 'new')
.option('-s, --cookie-strategy <strategy>', 'Cookie handling strategy (all|click|remove|block|none)', 'all')
.action(async (startUrl, options) => {
console.log(chalk.blue('š·ļø Starting web application spider...'));
console.log(chalk.gray(`š Target: ${startUrl}`));
console.log(chalk.gray(`š Output: ${options.outputDir}`));
// Validate required authentication if URL suggests it might need it
if (!options.username || !options.password) {
console.log(chalk.yellow('ā ļø No authentication credentials provided.'));
console.log(chalk.yellow(' Use -u <username> -p <password> if the application requires login.'));
}
const spider = new ApplicationSpider({
viewport: {
width: parseInt(options.width),
height: parseInt(options.height),
deviceScaleFactor: 1
},
headless: options.headless === 'false' ? false : 'new',
cookieStrategy: options.cookieStrategy,
waitTime: parseInt(options.wait),
maxDepth: parseInt(options.maxDepth),
maxFlows: parseInt(options.maxFlows),
maxPages: parseInt(options.maxPages),
flowMode: options.flowMode,
includeQueryParams: options.includeQueryParams,
outputDir: options.outputDir
});
try {
const result = await spider.spiderApplication(
startUrl,
options.username,
options.password
);
if (result.success) {
console.log(chalk.green('\nā
Spider completed successfully!'));
console.log(chalk.green(`š Summary:`));
console.log(chalk.white(` ⢠Flows discovered: ${result.summary.completedFlows}`));
console.log(chalk.white(` ⢠Total steps: ${result.summary.totalSteps}`));
console.log(chalk.white(` ⢠Screenshots: ${result.summary.screenshotCount}`));
console.log(chalk.white(` ⢠Unique URLs: ${result.summary.totalUrls}`));
console.log(chalk.cyan(`\nš Documentation generated in: ${result.summary.outputDirectory}`));
console.log(chalk.cyan(`š Start with: ${path.join(result.summary.outputDirectory, 'index.md')}`));
} else {
console.log(chalk.red('ā Spider completed with issues'));
}
} catch (error) {
console.error(chalk.red('ā Spider failed:'), error.message);
if (error.message.includes('Authentication failed')) {
console.log(chalk.yellow('\nš” Tips:'));
console.log(chalk.yellow(' ⢠Check your username and password'));
console.log(chalk.yellow(' ⢠Ensure the start URL leads to a login page'));
console.log(chalk.yellow(' ⢠Try with --headless false to see what\'s happening'));
}
process.exit(1);
}
});
program
.command('example')
.description('Show example batch file format')
.action(() => {
const example = [
{
url: 'https://example.com',
output: './screenshots/example-home.png',
fullPage: false
},
{
url: 'https://example.com/about',
output: './screenshots/example-about.png',
fullPage: true
}
];
console.log(chalk.blue('Example batch file format:'));
console.log(JSON.stringify(example, null, 2));
});
program.parse();