UNPKG

browser-debugger-cli

Version:

DevTools telemetry in your terminal. For humans and agents. Direct WebSocket to Chrome's debugging port.

145 lines 6.25 kB
/** * Peek command for previewing collected session data. */ import { runCommand } from '../commands/shared/CommandRunner.js'; import { jsonOption } from '../commands/shared/commonOptions.js'; import { handleDaemonConnectionError } from '../commands/shared/daemonErrorHandler.js'; import { fetchPreviewOutput, createErrorResult, } from '../commands/shared/dataFetcher.js'; import { setupFollowMode } from '../commands/shared/followMode.js'; import { positiveIntRule, resourceTypeRule } from '../commands/shared/validation.js'; import { filterByResourceType } from '../telemetry/filters.js'; import { OutputBuilder } from '../ui/OutputBuilder.js'; import { CommandError } from '../ui/errors/index.js'; import { formatPreview } from '../ui/formatters/preview.js'; import { followingPreviewMessage, stoppedFollowingPreviewMessage } from '../ui/messages/preview.js'; import { EXIT_CODES } from '../utils/exitCodes.js'; function parseOptions(options) { const lastN = positiveIntRule({ min: 1, max: 1000, default: 10 }).validate(options.last); const resourceTypes = resourceTypeRule().validate(options.type); return { lastN, resourceTypes }; } function handleValidationError(error, json) { if (error instanceof CommandError) { if (json) { const errorOptions = { exitCode: error.exitCode, }; if (error.metadata.suggestion) { errorOptions.suggestion = error.metadata.suggestion; } console.log(JSON.stringify(OutputBuilder.buildJsonError(error.message, errorOptions))); } else { console.error(error.message); if (error.metadata.suggestion) console.error(error.metadata.suggestion); } process.exit(error.exitCode); } console.error(error instanceof Error ? error.message : String(error)); process.exit(EXIT_CODES.INVALID_ARGUMENTS); } async function fetchAndFilterPreview(lastN, resourceTypes) { const result = await fetchPreviewOutput(lastN); if (!result.success) return result; const output = result.data; const unfilteredNetworkCount = output.data.network?.length ?? 0; if (resourceTypes.length === 0) { return { success: true, data: { output, unfilteredNetworkCount } }; } const filteredNetwork = output.data.network ? filterByResourceType(output.data.network, resourceTypes) : undefined; const filteredOutput = { ...output, data: { ...output.data, ...(filteredNetwork && { network: filteredNetwork }) }, }; return { success: true, data: { output: filteredOutput, unfilteredNetworkCount } }; } function createPreviewOptions(base, resourceTypes, unfilteredCount) { const options = { ...base }; if (base.follow) options.viewedAt = new Date(); if (resourceTypes.length > 0) { options.filteredTypes = resourceTypes; options.unfilteredNetworkCount = unfilteredCount; } return options; } async function runFollowMode(options, lastN, resourceTypes, baseOptions) { const showPreview = async () => { const result = await fetchAndFilterPreview(lastN, resourceTypes); if (!result.success) { const errorResult = handleDaemonConnectionError(result.error, { json: options.json, follow: true, retryIntervalMs: 1000, exitCode: result.exitCode, }); if (errorResult.shouldExit) process.exit(errorResult.exitCode); return; } console.clear(); const previewOptions = createPreviewOptions(baseOptions, resourceTypes, result.data.unfilteredNetworkCount); console.log(formatPreview(result.data.output, previewOptions)); }; await setupFollowMode(showPreview, { startMessage: followingPreviewMessage, stopMessage: stoppedFollowingPreviewMessage, intervalMs: 1000, }); } export function registerPeekCommand(program) { program .command('peek') .description('Preview collected data without stopping the session') .addOption(jsonOption()) .option('-v, --verbose', 'Use verbose output with full URLs and formatting', false) .option('-n, --network', 'Show only network requests', false) .option('-c, --console', 'Show only console messages', false) .option('-d, --dom', 'Show DOM/A11y tree data', false) .option('-f, --follow', 'Watch for updates (like tail -f)', false) .option('--last <count>', 'Show last N items (default: 10)', '10') .option('--type <types>', 'Filter network requests by resource type (comma-separated: Document,XHR,Fetch,etc.)') .action(async (options) => { if (options.network && !options.json) { console.error('Note: "bdg peek --network" is deprecated. Use "bdg network list" for enhanced filtering.'); } let lastN; let resourceTypes; try { const parsed = parseOptions(options); lastN = parsed.lastN; resourceTypes = parsed.resourceTypes; } catch (error) { handleValidationError(error, options.json ?? false); } const baseOptions = { json: options.json, network: options.network, console: options.console, dom: options.dom, last: lastN, verbose: options.verbose, follow: options.follow, }; if (options.follow) { await runFollowMode(options, lastN, resourceTypes, baseOptions); return; } await runCommand(async () => { const result = await fetchAndFilterPreview(lastN, resourceTypes); if (!result.success) { return createErrorResult(result.error, result.exitCode); } return { success: true, data: result.data.output }; }, options, (output) => { const previewOptions = createPreviewOptions(baseOptions, resourceTypes, output.data.network?.length ?? 0); return formatPreview(output, previewOptions); }); }); } //# sourceMappingURL=peek.js.map