#!/usr/bin/env node /** * Pull the CSV from the headless browser via CDP and assemble it on disk. * * Usage: * tsx scripts/_dump-browser-csv.ts * * Example: * tsx scripts/_dump-browser-csv.ts stable-browser-session/xxx 'window.__hbCsv' scripts/nss-hex-bolts.csv */ import { writeFileSync } from "node:fs"; const [, , viewIdExpr, expression, outPath] = process.argv; if (!viewIdExpr || !expression || !outPath) { console.error("Usage: tsx _dump-browser-csv.ts "); process.exit(1); } const port = 9222; const host = "127.0.0.1"; // Discover the page WebSocket URL. async function getWsUrl(): Promise { const r = await fetch(`http://${host}:${port}/json`); const tabs = (await r.json()) as Array<{ id: string; webSocketDebuggerUrl: string }>; const target = tabs.find((t) => t.id.startsWith(viewIdExpr)); if (!target) throw new Error(`tab not found for viewId prefix ${viewIdExpr}`); return target.webSocketDebuggerUrl; } async function evalChunked(ws: WebSocket, expression: string): Promise { const CHUNK = 6000; const full = await evalOnce(ws, expression); const out: string[] = []; for (let i = 0; i < full.length; i += CHUNK) { out.push(full.substring(i, i + CHUNK)); } return out.join(""); } function evalOnce( ws: WebSocket, expression: string, ): Promise { return new Promise((resolve, reject) => { const id = Math.floor(Math.random() * 1e9); const onMsg = (ev: MessageEvent) => { const msg = JSON.parse(ev.data); if (msg.id !== id) return; ws.removeEventListener("message", onMsg); if (msg.error) reject(new Error(msg.error.message)); else resolve(msg.result?.value ?? ""); }; ws.addEventListener("message", onMsg); ws.send( JSON.stringify({ id, method: "Runtime.evaluate", params: { expression, returnByValue: true }, }), ); }); } async function main() { const wsUrl = await getWsUrl(); const ws = new WebSocket(wsUrl); await new Promise((resolve, reject) => { ws.addEventListener("open", () => resolve()); ws.addEventListener("error", (e) => reject(new Error(String(e)))); }); const csv = await evalChunked(ws, expression); writeFileSync(outPath, csv); console.log(`Wrote ${csv.length} bytes to ${outPath}`); ws.close(); } main().catch((e) => { console.error("FATAL:", e); process.exit(1); });