// dump IndexedDB 结构 + Hive entry 格式 const { chromium } = require('playwright'); const BASE = 'http://127.0.0.1:8099'; (async () => { const browser = await chromium.launch({ headless: true }); const page = await (await browser.newContext()).newPage(); await page.goto(BASE + '/', { waitUntil: 'load', timeout: 60000 }); await page.waitForTimeout(7000); const result = await page.evaluate(async () => { const out = {}; const dbs = await indexedDB.databases(); out.databases = dbs.map(d => d.name); for (const db of dbs) { out[db.name] = []; await new Promise((resolve) => { const req = indexedDB.open(db.name); req.onsuccess = () => { const d = req.result; const stores = [...d.objectStoreNames]; out[db.name + '_stores'] = stores; if (stores.length === 0) { d.close(); resolve(); return; } const tx = d.transaction(stores[0], 'readonly'); const store = tx.objectStore(stores[0]); const allReq = store.getAll(); const keysReq = store.getAllKeys(); allReq.onsuccess = () => { out[db.name] = allReq.result.map((v, i) => { let hex = ''; if (v instanceof ArrayBuffer) { const u = new Uint8Array(v); hex = Array.from(u.slice(0, 40)).map(b => b.toString(16).padStart(2,'0')).join(' '); return { key: keysReq.result[i], valueBytes: v.byteLength, hexFirst40: hex }; } return { key: keysReq.result[i], value: typeof v === 'string' ? v.slice(0,80) : v }; }); }; tx.oncomplete = () => { d.close(); resolve(); }; }; req.onerror = () => resolve(); }); } return out; }); console.log(JSON.stringify(result, null, 2)); await browser.close(); })().catch(e => { console.error('失败:', e.message); process.exit(1); });