mirror of
https://github.com/imjasonh/apkviz
synced 2026-07-07 01:22:26 +00:00
This web application visualizes package dependencies in the Wolfi Linux distribution, providing powerful insights into the package ecosystem. Features: - Interactive force-directed dependency graph visualization - Shows both forward dependencies (what a package depends on) and reverse dependencies (what depends on it) - Click any node to re-center the visualization on that package - Transitive dependency analysis with toggle control - Advanced package analytics including: - Criticality scores showing how many packages depend on each package - Total size impact analysis (package + all dependencies) - Dependency depth metrics - Bus factor warnings for critical infrastructure packages - "Most Critical Packages" dashboard showing system-wide statistics - Real-time search with auto-complete - Different visual styles for direct vs transitive dependencies - Playwright-based testing infrastructure for automated UI testing Technical implementation: - TypeScript + D3.js for visualization - Webpack build system - Analyzes Wolfi's APKINDEX for package metadata - Efficient dependency graph algorithms - Responsive design with detailed package information panel 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
65 lines
No EOL
2.1 KiB
JavaScript
65 lines
No EOL
2.1 KiB
JavaScript
const { chromium } = require('playwright');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
async function quickDebug(command = 'screenshot') {
|
|
const browser = await chromium.launch({ headless: true });
|
|
const page = await browser.newPage();
|
|
|
|
// Capture all console output
|
|
const logs = [];
|
|
page.on('console', msg => logs.push(`[${msg.type()}] ${msg.text()}`));
|
|
page.on('pageerror', err => logs.push(`[ERROR] ${err.message}`));
|
|
page.on('requestfailed', req => logs.push(`[NETWORK] Failed: ${req.url()}`));
|
|
|
|
try {
|
|
await page.goto('http://localhost:8081', { waitUntil: 'networkidle', timeout: 10000 });
|
|
|
|
switch(command) {
|
|
case 'screenshot':
|
|
await page.screenshot({ path: 'playwright-output/debug.png', fullPage: true });
|
|
console.log('Screenshot saved to debug.png');
|
|
break;
|
|
|
|
case 'console':
|
|
await page.waitForTimeout(2000);
|
|
logs.forEach(log => console.log(log));
|
|
break;
|
|
|
|
case 'state':
|
|
const state = await page.evaluate(() => ({
|
|
title: document.title,
|
|
url: window.location.href,
|
|
errors: Array.from(document.querySelectorAll('.error, [data-error]')).map(el => el.textContent),
|
|
bodyPreview: document.body.innerText.substring(0, 200)
|
|
}));
|
|
console.log(JSON.stringify(state, null, 2));
|
|
break;
|
|
|
|
case 'click':
|
|
const selector = process.argv[3];
|
|
if (selector) {
|
|
await page.click(selector);
|
|
await page.waitForTimeout(1000);
|
|
await page.screenshot({ path: 'after-click.png', fullPage: true });
|
|
console.log('Clicked and saved screenshot');
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Always save logs
|
|
// Ensure output directory exists
|
|
if (!fs.existsSync('playwright-output')) {
|
|
fs.mkdirSync('playwright-output');
|
|
}
|
|
fs.writeFileSync('playwright-output/debug-logs.txt', logs.join('\n'));
|
|
|
|
} catch (error) {
|
|
console.error('Error:', error.message);
|
|
await page.screenshot({ path: 'playwright-output/error.png' }).catch(() => {});
|
|
}
|
|
|
|
await browser.close();
|
|
}
|
|
|
|
quickDebug(process.argv[2]); |