mirror of
https://github.com/imjasonh/apkviz
synced 2026-07-16 20:35:50 +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>
45 lines
No EOL
1.4 KiB
JavaScript
45 lines
No EOL
1.4 KiB
JavaScript
const { chromium } = require('playwright');
|
|
|
|
// Ensure output directory exists
|
|
const fs = require('fs');
|
|
if (!fs.existsSync('playwright-output')) {
|
|
fs.mkdirSync('playwright-output', { recursive: true });
|
|
}
|
|
|
|
async function testStats() {
|
|
const browser = await chromium.launch({ headless: false, slowMo: 100 });
|
|
const page = await browser.newPage();
|
|
|
|
await page.goto('http://localhost:8081', { waitUntil: 'networkidle' });
|
|
await page.waitForTimeout(2000);
|
|
|
|
// Search for different packages to see their stats
|
|
const testPackages = ['glibc', 'gcc', 'python', 'nodejs'];
|
|
|
|
for (const pkg of testPackages) {
|
|
console.log(`\nTesting ${pkg}...`);
|
|
|
|
// Clear search and type new package
|
|
await page.fill('#search', '');
|
|
await page.type('#search', pkg, { delay: 50 });
|
|
await page.waitForTimeout(2000);
|
|
|
|
// Check if stats are visible
|
|
const statsVisible = await page.$('#package-stats');
|
|
if (statsVisible) {
|
|
const statsContent = await page.$eval('#package-stats', el => el.textContent);
|
|
console.log('Stats found:', statsContent.substring(0, 100) + '...');
|
|
|
|
// Take screenshot
|
|
await page.screenshot({ path: `stats-${pkg}.png`, fullPage: true });
|
|
} else {
|
|
console.log('No stats panel found');
|
|
}
|
|
}
|
|
|
|
console.log('\nKeeping browser open for manual inspection...');
|
|
// Keep browser open
|
|
await new Promise(() => {});
|
|
}
|
|
|
|
testStats().catch(console.error); |